library(ggplot2)
library(tidyverse)
library(GGally)
library(ggpubr)

#load the dataframes for the figure

remove cells in the edges : pos.x > 45 & < 1150 pos.y > 45 & < 1000 ##add the replicate info


aic.df <- aic.df %>% 
  mutate(exp.field = paste0(str_split(cell.id, "_", simplify = T)[,2],"_",
                            str_split(cell.id, "_", simplify = T)[,3]),
    colony = case_when(exp.field %in% c("20min_s3", "20min_s4") ~ "Replicate 1", 
                            exp.field %in% c("20min_s5", "20min_s6") ~ "Replicate 2",
                            exp.field %in% c("20min_s7", "20min_s8" , "20min_s9") ~ "Replicate 3"))

aic.df <- aic.df %>% 
  mutate(colony = ifelse(degron == "stable" & red == "pup1-rfp", 
                         case_when(exp.field %in% c("20min_s4", "20min_s5") ~ "Replicate 1",
                                   exp.field %in% c("20min_s6", "20min_s7") ~ "Replicate 2",
                                   exp.field %in% c("20min_s8", "20min_s9") ~ "Replicate 3"), colony)) 
  # filter(value < 0.05)
  

##Cellular attributes

pup1.cell.attr <- read_csv("~/plots/all_data/all_pup1_cell_attr.csv")
Rows: 19396 Columns: 29
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (4): cell.id, degron, red, treatment
dbl (25): gfp.mean.bg.af.sub.new, gfp.sum.bg.af.sub, area, area.puncta, BB_B, BB_C, Elip_B, Elip_C, no.of.voxels, pos.x, pos.y, spherac...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

###pup1-RFP background

pup1.cell.attr <- pup1.cell.attr %>% 
  mutate(exp.field = paste0(str_split(cell.id, "_", simplify = T)[,2],"_",
                            str_split(cell.id, "_", simplify = T)[,3]),
    colony = case_when(exp.field %in% c("20min_s3", "20min_s4") ~ "Replicate 1", 
                            exp.field %in% c("20min_s5", "20min_s6") ~ "Replicate 2",
                            exp.field %in% c("20min_s7", "20min_s8" , "20min_s9") ~ "Replicate 3"))

pup1.cell.attr <- pup1.cell.attr %>% 
  mutate(colony = ifelse(degron == "stable" & red == "pup1-rfp", 
                         case_when(exp.field %in% c("20min_s4", "20min_s5") ~ "Replicate 1",
                                   exp.field %in% c("20min_s6", "20min_s7") ~ "Replicate 2",
                                   exp.field %in% c("20min_s8", "20min_s9") ~ "Replicate 3"), colony)) 
  
pup1.cell.attr %>%
  mutate(exp = str_split(exp.field, "_", simplify = T)[,1]) %>% split(.$exp)
$`20min`

$`40min`

$`60min`
NA

Adding the gfp.sum column for the stable GFP experiment

pup1.cell.attr <- read_csv("~/plots/pup1-rfp-gfp-decay/4-28-21-8hrGFP/data/gfp_stable_filtered.csv") %>% 
  filter(image.no == 1) %>% 
  dplyr::select(cell.id, gfpSumBgAFsub) %>% 
  mutate(cell.id = paste0(cell.id,"_","stable_pup1-rfp_none")) %>% 
  dplyr::rename("gfp.sum.bg.af.sub" = "gfpSumBgAFsub") %>% 
  left_join(pup1.cell.attr %>% 
              filter(degron == "stable") %>% 
              dplyr::select(-gfp.sum.bg.af.sub),., by = "cell.id") %>% 
  bind_rows(pup1.cell.attr %>% 
              filter(degron != "stable"),.)

removing multiple entries of the cell because some cell have more than one,

multiple.pup1 <- pup1.cell.attr %>% 
  mutate(dapi.mean.bg.sub.puncta = ifelse(is.na(dapi.mean.bg.sub.puncta), 0, dapi.mean.bg.sub.puncta) , 
         rfp.mean.bg.sub.puncta = ifelse(is.na(rfp.mean.bg.sub.puncta), 0 , rfp.mean.bg.sub.puncta)) %>% 
  filter(rfp.mean.bg.sub.puncta > 0) %>% 
  group_by(cell.id) %>% 
  tally() %>% 
  filter(n>1)

pup1.cell.attr<- pup1.cell.attr %>% 
  group_by(cell.id) %>% 
  mutate(rfp.mean.bg.sub.puncta = ifelse(cell.id %in% multiple.pup1$cell.id , mean(rfp.mean.bg.sub.puncta), rfp.mean.bg.sub.puncta),
         rfp.sum.bg.sub.puncta = ifelse(cell.id %in% multiple.pup1$cell.id, sum(rfp.mean.bg.sub.puncta), rfp.sum.bg.sub.puncta)) %>% 
    distinct(cell.id, .keep_all = TRUE) 
  

#proteasome inhibition experiments

protInhi.attr <- read_csv("~/plots/all_data/all_mg135_attr.csv") %>% 
  rename("cell.id" = "unique.trackID") %>% 
  filter(timepoint == 1) %>% 
  mutate(cell.id = paste0(cell.id ,"_",degron,"_",red,"_",treatment)) %>% 
  mutate(exp.field = paste0(str_split(cell.id, "_", simplify = T)[,2],"_",
                            str_split(cell.id, "_", simplify = T)[,3]),
    colony = case_when(exp.field %in% c("20min_s3", "20min_s4") ~ "Replicate 1", 
                            exp.field %in% c("20min_s5", "20min_s6") ~ "Replicate 2",
                            exp.field %in% c("20min_s7", "20min_s8" , "20min_s9") ~ "Replicate 3"))

multiple.proInh <- protInhi.attr %>% 
  mutate(dapi.mean.bg.sub.puncta = ifelse(is.na(dapi.mean.bg.sub.puncta), 0, dapi.mean.bg.sub.puncta) , 
         rfp.mean.bg.sub.puncta = ifelse(is.na(rfp.mean.bg.sub.puncta), 0 , rfp.mean.bg.sub.puncta)) %>% 
  filter(rfp.mean.bg.sub.puncta > 0) %>% 
  group_by(cell.id) %>% 
  tally() %>% 
  filter(n>1)

protInhi.attr <- protInhi.attr %>% 
  group_by(cell.id) %>% 
  mutate(rfp.mean.bg.sub.puncta = ifelse(cell.id %in% multiple.proInh$cell.id , mean(rfp.mean.bg.sub.puncta), rfp.mean.bg.sub.puncta),
         rfp.sum.bg.sub.puncta = ifelse(cell.id %in% multiple.proInh$cell.id, sum(rfp.mean.bg.sub.puncta), rfp.sum.bg.sub.puncta)) %>% 
    distinct(cell.id, .keep_all = TRUE)  
  

Adding the protein inhibition experiment data

pup1.proInhi.attr <- pup1.cell.attr %>% 
  bind_rows(.,protInhi.attr %>% 
              dplyr::select(-time, 
                            -timepoint,
                            -image.no, 
                            -ln.gfp, 
                            -ln.gfp.dif,
                            -trackID,
                            -gfp.intensity.center,
                            -gfp.int.mean,
                            -gfp.int.median,
                           -gfp.int.sum,
                           -no.of.triangles,
                           -field,
                           -time.dif.gfp,
                           -real.time.gfp,
                           -sample,
                           -avg.gfp.bg,
                           -Min_gfp,
                           -gfp.mean.bg.sub,
                           -value,
                           -t80,
                           -t95,
                           -threshold,
                           -threshold_95,
                           -gfp.mean.bg.af.sub,
                           -threshold_80,
                           -Mean_gfp,
                           -image,
                           -experiment,
                           -gfp.sum.bg.sub))

#keeping the parameters estimated from the 2-parameter with maturation model

#only dy.dm
dy.pup1.rep1.mat <- aic.df %>% 
  filter(red == "pup1-rfp") %>% 
  filter(ifelse(degron %in% c("stable","stable.2","stable.3"), dy < 0.1, dy < 0.5)) %>% 
  group_by(cell.id) %>% 
  filter(model == "dy.dm") %>% 
  mutate(dm = ifelse(is.na(dm), Inf, dm)) %>%
  filter( dm > 0.000015)

#count the number of cells in each experiment

dy.pup1.rep1.mat %>% group_by(degron, treatment) %>% tally()

#creating the df for the MLR

mlr.df <- dy.pup1.rep1.mat %>% 
  #left join with the df with cellular attributes
  left_join(.,pup1.proInhi.attr, by = c("cell.id","red","treatment","degron", "exp.field","colony")) %>% 
  #remove cells with no rfp puncta info 
  mutate(rfp.mean.bg.sub.puncta = ifelse(is.na(rfp.mean.bg.sub.puncta), 0, rfp.mean.bg.sub.puncta)) %>% 
  filter(rfp.mean.bg.sub.puncta > 0)

#checking how many cells there are in each experiment

mlr.df %>% group_by(degron, treatment) %>% tally()

##Removing the columns that I wont regress upon

mlr.df <- mlr.df %>% 
  filter(pos.x > 45 & pos.x < 1150,
  pos.y > 45 & pos.y < 1000) %>%
  dplyr::select(-f, 
         -rfp.mean.af.sub.puncta,
         -rfp.sum.af.sub.puncta, 
         -dapi.sum.af.sub.puncta,
         -dapi.mean.af.sub.puncta,
         -model, 
         -k,
         -fevals,
         -gevals, 
         -niter, 
         -convcode, 
         -kkt1,
         -kkt2,
         -value,
         -xtime, 
         # -treatment,
         -rfp.mean.bg.sub,
         -rfp.sum.bg.sub,
         -dapi.mean.bg.sub,
         -dapi.sum.bg.sub,
         -dapi.mean.bg.sub.puncta,
         -area.puncta,
         -BB_B,
         -BB_C,
         -pos.x,
         -pos.y,
         -gfp.sum.bg.af.sub,
         -rfp.sum.bg.sub.puncta,
         -no.of.voxels,
         -volume,
         -spheracity) %>% 
  mutate(shape = Elip_B/Elip_C, 
         t.half = log(2)/dy) %>%
  ungroup() %>%
  dplyr::select(-cell.id, 
                -red,
                -exp.field, 
                -aic,
                -Elip_B,
                -Elip_C, 
                -exp) 

#Regressors to use for MLR

regressors <- c("dm",
                "gfp.mean.bg.af.sub.new",
                # "gfp.sum.bg.af.sub",
                "area",
                # "no.of.voxels",
                # "spheracity",
                # "volume",
                "rfp.mean.bg.sub.puncta",
                # "rfp.sum.bg.sub.puncta",
                "dapi.sum.bg.sub.puncta",
                "shape")

#df where the two experiments of cln2 and stable-GFP are clubbed

mlr.df2 <- mlr.df %>% 
  filter(degron %in% c("cln2.3","mODC.2","stable.3","stable.2","cln2.4")) %>% 
  mutate(degron = case_when(degron %in% c("cln2.3","cln2.2","cln2","cln2.4") ~ "yeGFP-CLN2",
                            degron %in% c("mODC.2", "mODC")  ~ "yeGFP-mODC",
                            degron %in% c("stable","stable.2","stable.3") ~ "yeGFP")) 
  

#df to be used with step function

temp.df.list <- mlr.df2 %>% 
    filter(treatment == "none") %>%  
  # mutate( dm = log10(dm)) %>% 
  split(.$degron)

#using stepAIC from MASS

full.stepAIC.mass %>% map(.,broom::tidy)
$`GFP-CLN2`

$`GFP-mODC`

$yeGFP
NA

#step AIC with all the fp markers + cell shape

full.stepAIC <- lapply(temp.df.list, function(a){
  n <- nrow(a)
 step(lm(t.half ~ ., data = a %>% 
     dplyr::select(regressors,
                   t.half,
                   -dy, 
                   -treatment)), 
     direction = "backward", 
     trace = T,
     # k = log(n),
     k =2 ) #k = 2 when small dataset and k = log(n) where n = no. of observations for when the dataset is large
})
Note: Using an external vector in selections is ambiguous.
ℹ Use `all_of(regressors)` instead of `regressors` to silence this message.
ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.
Start:  AIC=5023.53
t.half ~ dm + gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta + 
    dapi.sum.bg.sub.puncta + shape

                         Df Sum of Sq   RSS    AIC
- rfp.mean.bg.sub.puncta  1      32.7 36232 5023.0
- shape                   1      38.8 36239 5023.3
- area                    1      39.3 36239 5023.3
<none>                                36200 5023.5
- dm                      1     247.6 36447 5032.5
- dapi.sum.bg.sub.puncta  1     918.2 37118 5061.8
- gfp.mean.bg.af.sub.new  1    7805.7 44006 5335.7

Step:  AIC=5022.98
t.half ~ dm + gfp.mean.bg.af.sub.new + area + dapi.sum.bg.sub.puncta + 
    shape

                         Df Sum of Sq   RSS    AIC
- shape                   1      37.2 36270 5022.6
<none>                                36232 5023.0
- area                    1      89.4 36322 5024.9
- dm                      1     259.8 36492 5032.5
- dapi.sum.bg.sub.puncta  1     970.8 37203 5063.5
- gfp.mean.bg.af.sub.new  1    7803.3 44036 5334.8

Step:  AIC=5022.63
t.half ~ dm + gfp.mean.bg.af.sub.new + area + dapi.sum.bg.sub.puncta

                         Df Sum of Sq   RSS    AIC
<none>                                36270 5022.6
- area                    1      82.2 36352 5024.3
- dm                      1     249.7 36519 5031.7
- dapi.sum.bg.sub.puncta  1    1048.1 37318 5066.5
- gfp.mean.bg.af.sub.new  1    7848.3 44118 5335.8
Start:  AIC=1261.28
t.half ~ dm + gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta + 
    dapi.sum.bg.sub.puncta + shape

                         Df Sum of Sq    RSS    AIC
- shape                   1      1.67 3519.1 1260.1
- dm                      1      2.15 3519.6 1260.3
<none>                                3517.5 1261.3
- rfp.mean.bg.sub.puncta  1      5.47 3522.9 1261.8
- area                    1     85.84 3603.3 1299.2
- dapi.sum.bg.sub.puncta  1     89.54 3607.0 1300.9
- gfp.mean.bg.af.sub.new  1    479.97 3997.4 1471.2

Step:  AIC=1260.06
t.half ~ dm + gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta + 
    dapi.sum.bg.sub.puncta

                         Df Sum of Sq    RSS    AIC
- dm                      1      2.17 3521.3 1259.1
<none>                                3519.1 1260.1
- rfp.mean.bg.sub.puncta  1      5.05 3524.2 1260.4
- area                    1     84.64 3603.8 1297.4
- dapi.sum.bg.sub.puncta  1     87.90 3607.0 1298.9
- gfp.mean.bg.af.sub.new  1    482.37 4001.5 1470.9

Step:  AIC=1259.08
t.half ~ gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta + 
    dapi.sum.bg.sub.puncta

                         Df Sum of Sq    RSS    AIC
<none>                                3521.3 1259.1
- rfp.mean.bg.sub.puncta  1      5.13 3526.4 1259.5
- area                    1     85.97 3607.3 1297.0
- dapi.sum.bg.sub.puncta  1     87.30 3608.6 1297.7
- gfp.mean.bg.af.sub.new  1    493.27 4014.6 1474.3
Start:  AIC=922.36
t.half ~ dm + gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta + 
    dapi.sum.bg.sub.puncta + shape

                         Df Sum of Sq    RSS     AIC
<none>                                2628.7  922.36
- shape                   1      7.60 2636.3  924.18
- area                    1     49.53 2678.2  945.06
- rfp.mean.bg.sub.puncta  1     56.77 2685.5  948.63
- dapi.sum.bg.sub.puncta  1     93.01 2721.7  966.37
- dm                      1    105.69 2734.4  972.52
- gfp.mean.bg.af.sub.new  1    561.29 3190.0 1176.40
full.stepAIC %>% 
  map(., broom::glance) %>% 
  bind_rows(.id = "sample") 
  # filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3"))

full.stepAIC %>% 
  map(., broom::tidy) 
$yeGFP

$`yeGFP-CLN2`

$`yeGFP-mODC`
  # bind_rows(.id = "sample") %>% 
  # filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3"), 
         # p.value < 0.05) %>% 

full.stepAIC %>% 
  map(.,function(a){
    a$anova 
  }) %>% 
  bind_rows(.,.id = "degron") %>% 
  mutate(Step = as.character(Step), 
         Step = ifelse(Step == "", "Full",Step)) %>% 
  group_by(degron) %>% 
  mutate(del.aic = AIC[1]-AIC) 


full.stepAIC.fp %>% 
  map(.,function(a){
    a$anova 
  }) %>% 
  bind_rows(.,.id = "degron") %>% 
  mutate(Step = as.character(Step), 
         Step = ifelse(Step == "", "Full",Step)) %>% 
  group_by(degron) %>% 
  mutate(del.aic = AIC[1]-AIC) 
NA
NA

#step AIC with only the fluorescent markers

#looking at which regressor contributes to the overall variability 
full.stepAIC.fp %>% 
  map(., broom::tidy) 
$`GFP-CLN2`

$`GFP-mODC`

$yeGFP
NA

Variance in t-half explained by each regressor using anova

var.explained
$yeGFP

$`yeGFP-CLN2`

$`yeGFP-mODC`
NA

#plotting the variance explained

#plots:

gfp.6.cor.plt
`geom_smooth()` using formula 'y ~ x'

with protein inhibition

 mlr.df %>%
  mutate(dm = log10(dm)) %>% 
  filter(degron %in% c("mODC")) %>%
  # filter(!(treatment %in% c("none", "dmso1","50uM")), 
         # ifelse(treatment == "5uM", t.half < 138.6294, t.half == t.half)) %>%  
  dplyr::select(t.half,
         regressors,
         degron,
         treatment) %>%
  rename(
    "GFP" = "gfp.mean.bg.af.sub.new",
    "Pup1-tDimer" = "rfp.mean.bg.sub.puncta",
    "DNA" = "dapi.sum.bg.sub.puncta",
    "Area" = "area"
  ) %>%
  pivot_longer(cols = 2:7) %>%
  mutate(degron = case_when(
    degron %in% c("mODC")  ~ "yeGFP-mODC"),
    treatment = factor(treatment, levels = c("none","dmso1","dmso2","1uM","2.5uM","5uM","50uM"))) %>%
  filter(!(name %in% c("shape","dm")),
         !(treatment %in% c("none","dmso1","50uM")), 
         t.half < 130) %>% 
  
  ggplot(., aes(x = value, y = t.half)) +
      ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
      stat_cor(size = 2) +
      geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
      facet_grid(treatment ~ name, scales = "free") +
      theme_bw() +
      labs(x = NULL) +
      theme(text = element_text(size = 8),
            axis.text.x = element_text(angle = 30),
            legend.key.size = unit(2,"mm"), 
            legend.position = "none")+
  ylab("Half-Life [min.]")+
  xlab("A.U")
Warning: Ignoring unknown parameters: guides
`geom_smooth()` using formula 'y ~ x'

#stepAIC with proteasome inhibition experiments With all fp regressors

temp.df.list.dmso <- mlr.df %>% 
    filter(treatment != "none", t.half < 130) %>%  
  split(.$treatment)

full.stepAIC.fp.dmso <- lapply(temp.df.list.dmso, function(a){
 step(lm(t.half ~ ., data = a %>% 
     dplyr::select(regressors.fp,
                   t.half,
                   -dy, 
                   -treatment)), 
     direction = "backward", trace = T)
})

with fp regressors + celluar shape

temp.df.list.dmso <- mlr.df %>% 
    filter(treatment != "none", t.half < 130) %>%  
  split(.$treatment)

full.stepAIC.dmso <- lapply(temp.df.list.dmso, function(a){
 step(lm(t.half ~ ., data = a %>% 
     dplyr::select(regressors.fp,
                   t.half,
                   -dy, 
                   -treatment)), 
     direction = "backward", trace = T)
})

Variance in t-half explained by each regressor

full.stepAIC.dmso %>% 
  map(., anova %>% as.data.frame) %>% 
  bind_rows(.id = "sample") %>% 
  rownames_to_column(var = "predictor") %>% 
  # filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3")) %>% 
  group_by(sample) %>% 
  mutate(var.exp = (value.Sum.Sq/sum(value.Sum.Sq))*100) %>% 
  split(.$sample)

full.stepAIC.fp.dmso %>% 
  map(., anova %>% as.data.frame) %>% 
  bind_rows(.id = "sample") %>% 
  rownames_to_column(var = "predictor") %>% 
  # filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3")) %>% 
  group_by(sample) %>% 
  mutate(var.exp = (value.Sum.Sq/sum(value.Sum.Sq))*100) %>% 
  split(.$sample)
full.stepAIC.dmso %>% 
  map(., anova %>% as.data.frame) %>% 
  bind_rows(.id = "sample") %>% 
  rownames_to_column(var = "predictor") %>% 
  # filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3")) %>% 
  group_by(sample) %>% 
  mutate(var.exp = (value.Sum.Sq/sum(value.Sum.Sq))*100, 
         predictor = str_split(predictor, pattern = "\\.\\.\\.", simplify = T)[,1], 
         predictor = case_when(predictor == "gfp.mean.bg.af.sub.new" ~ "GFP" ,
                               predictor == "area" ~ "Area",
                               predictor == "rfp.mean.bg.sub.puncta" ~ "Pup1",
                               predictor == "dapi.sum.bg.sub.puncta" ~ "DNA" ,
                               predictor == "shape" ~ "Shape", 
                               predictor == "dm" ~ "Rate of Maturation"
                               , 
                               TRUE~predictor)) %>% 
  split(.$sample)
$`1uM`

$`2.5uM`

$`50uM`

$`5uM`

$dmso1

$dmso2
NA
mlr.df %>%
  mutate(dm = log10(dm)) %>% 
  filter(degron %in% c ("mODC") ) %>%
  filter(!(treatment %in% c("none", "dmso1","50uM")), 
         ifelse(treatment == "5uM", t.half < 138.6294, t.half == t.half)) %>% 
  dplyr::select(t.half,
         regressors,
         degron,
         treatment) %>% 
  ggplot(.,aes(x = area, y = rfp.mean.bg.sub.puncta))+
  geom_point()+
  geom_smooth(method = "lm", se = F)+
  facet_wrap(~treatment)+
  stat_cor()

#ggpairs

gfp.area.cor.ggPair
$`yeGFP-mODC`

 plot: [1,1] [====>----------------------------------------------------------------------------------]  6% est: 0s 
 plot: [1,2] [==========>----------------------------------------------------------------------------] 12% est: 1s 
 plot: [1,3] [===============>-----------------------------------------------------------------------] 19% est: 1s 
 plot: [1,4] [=====================>-----------------------------------------------------------------] 25% est: 1s 
 plot: [2,1] [==========================>------------------------------------------------------------] 31% est: 1s `geom_smooth()` using formula 'y ~ x'

 plot: [2,2] [================================>------------------------------------------------------] 38% est: 1s 
 plot: [2,3] [=====================================>-------------------------------------------------] 44% est: 1s 
 plot: [2,4] [===========================================>-------------------------------------------] 50% est: 1s 
 plot: [3,1] [================================================>--------------------------------------] 56% est: 1s `geom_smooth()` using formula 'y ~ x'

 plot: [3,2] [=====================================================>---------------------------------] 62% est: 1s `geom_smooth()` using formula 'y ~ x'

 plot: [3,3] [===========================================================>---------------------------] 69% est: 0s 
 plot: [3,4] [================================================================>----------------------] 75% est: 0s 
 plot: [4,1] [======================================================================>----------------] 81% est: 0s `geom_smooth()` using formula 'y ~ x'

 plot: [4,2] [===========================================================================>-----------] 88% est: 0s `geom_smooth()` using formula 'y ~ x'

 plot: [4,3] [=================================================================================>-----] 94% est: 0s `geom_smooth()` using formula 'y ~ x'

 plot: [4,4] [=======================================================================================]100% est: 0s 
                                                                                                                   

$`yeGFP-CLN2`

 plot: [1,1] [====>----------------------------------------------------------------------------------]  6% est: 0s 
 plot: [1,2] [==========>----------------------------------------------------------------------------] 12% est: 0s 
 plot: [1,3] [===============>-----------------------------------------------------------------------] 19% est: 1s 
 plot: [1,4] [=====================>-----------------------------------------------------------------] 25% est: 1s 
 plot: [2,1] [==========================>------------------------------------------------------------] 31% est: 1s `geom_smooth()` using formula 'y ~ x'

 plot: [2,2] [================================>------------------------------------------------------] 38% est: 1s 
 plot: [2,3] [=====================================>-------------------------------------------------] 44% est: 1s 
 plot: [2,4] [===========================================>-------------------------------------------] 50% est: 1s 
 plot: [3,1] [================================================>--------------------------------------] 56% est: 1s `geom_smooth()` using formula 'y ~ x'

 plot: [3,2] [=====================================================>---------------------------------] 62% est: 1s `geom_smooth()` using formula 'y ~ x'

 plot: [3,3] [===========================================================>---------------------------] 69% est: 0s 
 plot: [3,4] [================================================================>----------------------] 75% est: 0s 
 plot: [4,1] [======================================================================>----------------] 81% est: 0s `geom_smooth()` using formula 'y ~ x'

 plot: [4,2] [===========================================================================>-----------] 88% est: 0s `geom_smooth()` using formula 'y ~ x'

 plot: [4,3] [=================================================================================>-----] 94% est: 0s `geom_smooth()` using formula 'y ~ x'

 plot: [4,4] [=======================================================================================]100% est: 0s 
                                                                                                                   

$yeGFP

 plot: [1,1] [====>----------------------------------------------------------------------------------]  6% est: 0s 
 plot: [1,2] [==========>----------------------------------------------------------------------------] 12% est: 0s 
 plot: [1,3] [===============>-----------------------------------------------------------------------] 19% est: 1s 
 plot: [1,4] [=====================>-----------------------------------------------------------------] 25% est: 1s 
 plot: [2,1] [==========================>------------------------------------------------------------] 31% est: 1s `geom_smooth()` using formula 'y ~ x'

 plot: [2,2] [================================>------------------------------------------------------] 38% est: 1s 
 plot: [2,3] [=====================================>-------------------------------------------------] 44% est: 0s 
 plot: [2,4] [===========================================>-------------------------------------------] 50% est: 0s 
 plot: [3,1] [================================================>--------------------------------------] 56% est: 0s `geom_smooth()` using formula 'y ~ x'

 plot: [3,2] [=====================================================>---------------------------------] 62% est: 0s `geom_smooth()` using formula 'y ~ x'

 plot: [3,3] [===========================================================>---------------------------] 69% est: 0s 
 plot: [3,4] [================================================================>----------------------] 75% est: 0s 
 plot: [4,1] [======================================================================>----------------] 81% est: 0s `geom_smooth()` using formula 'y ~ x'

 plot: [4,2] [===========================================================================>-----------] 88% est: 0s `geom_smooth()` using formula 'y ~ x'

 plot: [4,3] [=================================================================================>-----] 94% est: 0s `geom_smooth()` using formula 'y ~ x'

 plot: [4,4] [=======================================================================================]100% est: 0s 
                                                                                                                   

ggsave(plot = gfp.area.cor.ggPair$`yeGFP-mODC`, filename = "gfp_mODC_4Cor_ggP.png", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)

ggsave(plot = gfp.area.cor.ggPair$`yeGFP-mODC`, filename = "gfp_mODC_4Cor_ggP.pdf", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)

ggsave(plot = gfp.area.cor.ggPair$`yeGFP-CLN2`, filename = "gfp_cln2_4Cor_ggP.png", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)

ggsave(plot = gfp.area.cor.ggPair$`yeGFP-CLN2`, filename = "gfp_cln2_4Cor_ggP.pdf", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)

ggsave(plot = gfp.area.cor.ggPair$`yeGFP`, filename = "gfp_4Cor_ggP.png", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)

ggsave(plot = gfp.area.cor.ggPair$`yeGFP`, filename = "gfp_4Cor_ggP.pdf", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
test.ggP <- (wrap_elements(ggmatrix_gtable(gfp.area.cor.ggPair$`yeGFP-mODC`))|wrap_elements(ggmatrix_gtable(gfp.area.cor.ggPair$`yeGFP-CLN2`))| wrap_elements(ggmatrix_gtable(gfp.area.cor.ggPair$yeGFP)))+
 plot_annotation(tag_levels = "A")
ggsave(plot = test.ggP, filename = "test_ggP.pdf", path = "~/plots/paper1/figures/fig_2/", width = 6.5, height = 3)

#area vs pup1 vs dna vs gfp

df_corSup_fig <- mlr.df %>%
  filter(degron %in% c("mODC.2", "cln2.3", "cln2.4", "stable.2", "stable.3")) %>%
  dplyr::select(t.half,
         regressors,
         degron) %>%
  rename(
    "GFP" = "gfp.mean.bg.af.sub.new",
    "Pup1-tDimer" = "rfp.mean.bg.sub.puncta",
    "DNA" = "dapi.sum.bg.sub.puncta",
    "Area" = "area"
  ) %>%
  dplyr::select(Area, DNA, `Pup1-tDimer`,GFP,degron ) %>% 
  mutate(
    degron = case_when(
      degron %in% c("cln2.3", "cln2.4") ~ "yeGFP-CLN2",
      degron %in% c("mODC.2")  ~ "yeGFP-mODC",
      degron %in% c("stable.2", "stable.3") ~ "yeGFP"
    ),
    degron = factor(degron , levels = c("yeGFP-mODC", "yeGFP-CLN2", "yeGFP"))
  ) 

area.pup1 <- df_corSup_fig %>% 
  filter(degron == "yeGFP-mODC") %>% 
  ggplot(.,aes(x = Area, y = `Pup1-tDimer`))+
  ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
      stat_cor(size = 3) +
      geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
      theme_bw() +
      labs(x = NULL) +
      theme(text = element_text(size = 8),
            axis.text.x = element_text(angle = 30),
            legend.key.size = unit(2,"mm"), 
            legend.position = "none", 
            axis.line = element_line(size = 0.1))+
  ylab("Pup1-tDimer [A.U]")+
  xlab("Area [A.U]")
Warning: Ignoring unknown parameters: guides
dna.pup1 <- df_corSup_fig %>% 
  filter(degron == "yeGFP-mODC") %>% 
  ggplot(.,aes(x = DNA, y = `Pup1-tDimer`))+
  ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
      stat_cor(size = 3) +
      geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
      theme_bw() +
      labs(x = NULL) +
      theme(text = element_text(size = 8),
            axis.text.x = element_text(angle = 30),
            legend.key.size = unit(2,"mm"), 
            legend.position = "none", 
            axis.line = element_line(size = 0.1))+
  ylab("Pup1-tDimer [A.U]")+
  xlab("DNA [A.U]")
Warning: Ignoring unknown parameters: guides
dna.area <- df_corSup_fig %>%
  filter(degron == "yeGFP-mODC") %>% 
  ggplot(.,aes(x = DNA, y = Area))+
  ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
      stat_cor(size = 3) +
      geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
      theme_bw() +
      labs(x = NULL) +
      theme(text = element_text(size = 8),
            axis.text.x = element_text(angle = 30),
            legend.key.size = unit(2,"mm"), 
            legend.position = "none", 
            axis.line = element_line(size = 0.1))+
  ylab("Area [A.U]")+
  xlab("DNA [A.U]")
Warning: Ignoring unknown parameters: guides
gfpInt.cor.plt <- df_corSup_fig %>% 
  pivot_longer(cols = 1:3) %>% 
  # filter(degron == "yeGFP-mODC") %>% 
  ggplot(.,aes(x = value, y = GFP))+
  ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
      stat_cor(size = 3) +
      geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
  facet_wrap(degron~name, scales = "free")+
      theme_bw() +
      labs(x = NULL) +
      theme(text = element_text(size = 8),
            axis.text.x = element_text(angle = 30),
            legend.key.size = unit(2,"mm"), 
            legend.position = "none", 
            axis.line = element_line(size = 0.1))+
  xlab("A.U")
Warning: Ignoring unknown parameters: guides
test_cor
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'

#Partial correlations ppcor

#partial correlations
ppCor.list <- mlr.df2 %>% 
  filter(treatment == "none") %>% split(.$degron) %>% 
  map(.,function(a){
    a <- a %>% 
      dplyr::select(t.half, area,  dapi.sum.bg.sub.puncta, rfp.mean.bg.sub.puncta, gfp.mean.bg.af.sub.new) %>% 
      na.omit()
    ppcor::pcor(a)
  })

#correlations
cor.all <- mlr.df2 %>% 
  filter(treatment == "none") %>%  
  split(.$degron) %>% 
  map(.,function(a){
     a <- a %>% 
      dplyr::select(t.half, area, dapi.sum.bg.sub.puncta,rfp.mean.bg.sub.puncta, gfp.mean.bg.af.sub.new) %>% 
      na.omit()
     cor(a)
  })
ppCor.df <- ppCor.list %>% 
  map(.,function(a){
    a$estimate %>% 
      as.data.frame() %>% 
      rownames_to_column(var = "regressor") %>% 
      dplyr::select(t.half, regressor) %>% 
      left_join(.,a$p.value%>% 
                  as.data.frame() %>% 
                  rownames_to_column(var = "regressor") %>% 
                  rename("p.value" = "t.half") %>% 
      dplyr::select(p.value, regressor), by = "regressor")
  }) %>% 
  bind_rows(.id = "degron")

single.core.df <- cor.all %>% 
  map(.,function(a){
    a%>% 
      as.data.frame() %>% 
      rownames_to_column(var = "regressor") %>% 
      dplyr::select(t.half, regressor)
  }) %>% 
  bind_rows(.id = "degron") %>% 
  rename("single.core"="t.half")
ppCoor.fig <- ppCor.df %>% 
  left_join(.,single.core.df, by = c("degron","regressor")) %>% 
  rename("Partial-Pariwise"="t.half",
         "Standard-Pariwise" = "single.core") %>% 
  pivot_longer(cols = c("Partial-Pariwise","Standard-Pariwise")) %>% 
   mutate(regressor = case_when(regressor == "gfp.mean.bg.af.sub.new" ~ "GFP" ,
                               regressor == "area" ~ "Area",
                               regressor == "rfp.mean.bg.sub.puncta" ~ "Pup1",
                               regressor == "dapi.sum.bg.sub.puncta" ~ "DNA" ,
                               regressor == "t.half" ~ "half-life"), 
          degron = factor(degron, levels = c("yeGFP-mODC","yeGFP-CLN2","yeGFP")), 
          name = factor(name , levels = c("Standard-Pariwise", "Partial-Pariwise")), 
          sig = stars.pval(p.value), 
          sig = ifelse(sig == " ", "NS", sig)) %>% 
  # filter(p.value < 0.05) %>% 
  filter(regressor != "half-life") %>% 
  ggplot(.,aes(x = regressor , y = value, fill = name))+
  geom_col(width = 0.5, position = "dodge")+
  facet_wrap(~degron)+
  geom_hline(yintercept = 0, size = 0.1)+
  scale_y_continuous(breaks = seq(-0.5,0.5, by = 0.1))+
  theme_pubr()+
  theme(text = element_text(size = 8),
            legend.key.size = unit(4,"mm"),
        legend.position = "top", 
        axis.line = element_line(size = 0.1),
        strip.background = element_blank())+
  scale_fill_manual(values = c("lightsteelblue4" ," steelblue4"), name = NULL)+
  ylab("Correlation with Half-life ")+
  xlab("Cellular features")+
  labs(title = "C")

ppCoor.fig

#patchwork for 4 cellular features (area, gfp, dapi, pup1) and t-half

gfp.4cor.hf.ppCor.plt
`geom_smooth()` using formula 'y ~ x'

ggsave(plot = gfp.4cor.hf.ppCor.plt, filename = "gfp_4cor_halfLife_ppcor.png", path = "~/plots/paper1/figures/fig_2/", width = 7, height = 9)
`geom_smooth()` using formula 'y ~ x'

#with protein inhibion

ppCor.PrtIn.list <- mlr.df %>% 
    filter(treatment != "none") %>%  
  filter(ifelse(treatment == "5uM", t.half < 138.6294, t.half == t.half)) %>% 
  split(.$treatment) %>% 
  map(.,function(a){
    a <- a %>% 
      dplyr::select(t.half, area, dapi.sum.bg.sub.puncta, rfp.mean.bg.sub.puncta, gfp.mean.bg.af.sub.new) %>%
      na.omit()
    ppcor::pcor(a)
  })

cor.PrtIn.all <- mlr.df %>% 
    filter(treatment != "none") %>%  
  filter(ifelse(treatment == "5uM", t.half < 138.6294, t.half == t.half)) %>% 
  split(.$treatment) %>% 
  map(.,function(a){
    a <- a %>% 
      dplyr::select(t.half, area, dapi.sum.bg.sub.puncta, rfp.mean.bg.sub.puncta, gfp.mean.bg.af.sub.new) %>% 
      na.omit()
    cor(a)
  })
ppCor.PrtIn.df <- ppCor.PrtIn.list %>% 
  map(.,function(a){
    a$estimate %>% 
      as.data.frame() %>% 
      rownames_to_column(var = "regressor") %>% 
      dplyr::select(t.half, regressor) %>% 
      left_join(.,a$p.value%>% 
                  as.data.frame() %>% 
                  rownames_to_column(var = "regressor") %>% 
                  rename("p.value" = "t.half") %>% 
      dplyr::select(p.value, regressor), by = "regressor")
  }) %>% 
  bind_rows(.id = "treatment")

single.core.Prtn.df <- cor.PrtIn.all %>% 
  map(.,function(a){
    a%>% 
      as.data.frame() %>% 
      rownames_to_column(var = "regressor") %>% 
      dplyr::select(t.half, regressor)
  }) %>% 
  bind_rows(.id = "treatment") %>% 
  rename("single.core"="t.half")

correlation of pup1 with mODC with treated with proteasome inhibitors

#when you normalize pup1 with the area

mlr.df %>%
  mutate(dm = log10(dm)) %>% 
  filter(degron %in% c("mODC.2", "cln2.3", "cln2.4", "stable.2", "stable.3")) %>%
  dplyr::select(t.half,
         regressors,
         degron) %>%
  rename(
    "GFP" = "gfp.mean.bg.af.sub.new",
    "Pup1-tDimer" = "rfp.mean.bg.sub.puncta",
    "DNA" = "dapi.sum.bg.sub.puncta",
    "Area" = "area"
  ) %>%
  mutate(norm.pup1 = `Pup1-tDimer`/Area) %>% 
  pivot_longer(cols = c(2:7,9)) %>%
  mutate(degron = case_when(
      degron %in% c("cln2.3", "cln2.2", "cln2", "cln2.4") ~ "yeGFP-CLN2",
      degron %in% c("mODC.2", "mODC")  ~ "yeGFP-mODC",
      degron %in% c("stable", "stable.2", "stable.3") ~ "yeGFP"
    ),
    degron = factor(degron , levels = c("yeGFP-mODC", "yeGFP-CLN2", "yeGFP"))
  ) %>%
  filter(!(name %in% c("shape","dm"))) %>% 
  ggplot(., aes(x = value, y = t.half)) +
      ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
      stat_cor(size = 2) +
      geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
      facet_wrap(degron ~ name, scales = "free", ncol = 4) +
      theme_bw() +
      labs(x = NULL) +
      theme(text = element_text(size = 8),
            axis.text.x = element_text(angle = 30),
            legend.key.size = unit(2,"mm"), 
            legend.position = "none")+
  ylab("Half-Life [min.]")+
  xlab("A.U")
LS0tCnRpdGxlOiAiQ29ycmVsYXRpb25zIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KEdHYWxseSkKbGlicmFyeShnZ3B1YnIpCmxpYnJhcnkobGF0ZXgyZXhwKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShndG9vbHMpCmBgYAoKI2xvYWQgdGhlIGRhdGFmcmFtZXMgZm9yIHRoZSBmaWd1cmUKYGBge3J9CmFpYy5kZiA8LSByZWFkX2Nzdigifi9wbG90cy9hbGxfZGF0YS9haWMuY3N2IikKYGBgCgoKcmVtb3ZlIGNlbGxzIGluIHRoZSBlZGdlcyA6CnBvcy54ID4gNDUgJiA8IDExNTAKcG9zLnkgPiA0NSAmIDwgMTAwMAojI2FkZCB0aGUgcmVwbGljYXRlIGluZm8gCmBgYHtyfQphaWMuZGYgPC0gYWljLmRmICU+JSAKICBtdXRhdGUoZXhwLmZpZWxkID0gcGFzdGUwKHN0cl9zcGxpdChjZWxsLmlkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDJdLCJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9zcGxpdChjZWxsLmlkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDNdKSwKICAgIGNvbG9ueSA9IGNhc2Vfd2hlbihleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zMyIsICIyMG1pbl9zNCIpIH4gIlJlcGxpY2F0ZSAxIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNSIsICIyMG1pbl9zNiIpIH4gIlJlcGxpY2F0ZSAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3M3IiwgIjIwbWluX3M4IiAsICIyMG1pbl9zOSIpIH4gIlJlcGxpY2F0ZSAzIikpCgphaWMuZGYgPC0gYWljLmRmICU+JSAKICBtdXRhdGUoY29sb255ID0gaWZlbHNlKGRlZ3JvbiA9PSAic3RhYmxlIiAmIHJlZCA9PSAicHVwMS1yZnAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2Vfd2hlbihleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNCIsICIyMG1pbl9zNSIpIH4gIlJlcGxpY2F0ZSAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNiIsICIyMG1pbl9zNyIpIH4gIlJlcGxpY2F0ZSAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zOCIsICIyMG1pbl9zOSIpIH4gIlJlcGxpY2F0ZSAzIiksIGNvbG9ueSkpIAogIApgYGAKCiMjQ2VsbHVsYXIgYXR0cmlidXRlcwpgYGB7cn0KcHVwMS5jZWxsLmF0dHIgPC0gcmVhZF9jc3YoIn4vcGxvdHMvYWxsX2RhdGEvYWxsX3B1cDFfY2VsbF9hdHRyLmNzdiIpCmBgYAoKIyMjcHVwMS1SRlAgYmFja2dyb3VuZApgYGB7cn0KcHVwMS5jZWxsLmF0dHIgPC0gcHVwMS5jZWxsLmF0dHIgJT4lIAogIG11dGF0ZShleHAuZmllbGQgPSBwYXN0ZTAoc3RyX3NwbGl0KGNlbGwuaWQsICJfIiwgc2ltcGxpZnkgPSBUKVssMl0sIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX3NwbGl0KGNlbGwuaWQsICJfIiwgc2ltcGxpZnkgPSBUKVssM10pLAogICAgY29sb255ID0gY2FzZV93aGVuKGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3MzIiwgIjIwbWluX3M0IikgfiAiUmVwbGljYXRlIDEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3M1IiwgIjIwbWluX3M2IikgfiAiUmVwbGljYXRlIDIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwLmZpZWxkICVpbiUgYygiMjBtaW5fczciLCAiMjBtaW5fczgiICwgIjIwbWluX3M5IikgfiAiUmVwbGljYXRlIDMiKSkKCnB1cDEuY2VsbC5hdHRyIDwtIHB1cDEuY2VsbC5hdHRyICU+JSAKICBtdXRhdGUoY29sb255ID0gaWZlbHNlKGRlZ3JvbiA9PSAic3RhYmxlIiAmIHJlZCA9PSAicHVwMS1yZnAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2Vfd2hlbihleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNCIsICIyMG1pbl9zNSIpIH4gIlJlcGxpY2F0ZSAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNiIsICIyMG1pbl9zNyIpIH4gIlJlcGxpY2F0ZSAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zOCIsICIyMG1pbl9zOSIpIH4gIlJlcGxpY2F0ZSAzIiksIGNvbG9ueSkpIAogIApgYGAKCmBgYHtyfQojcmVtb3ZpbmcgdGhlIDQwbWluIGFuZCA2MG1pbiBleHBlcmltZW50cyBmcm9tIHRoZSBzdGFibGUgZ2ZwIGV4cGVyaW1lbnRzCnB1cDEuY2VsbC5hdHRyIDwtIHB1cDEuY2VsbC5hdHRyICU+JQogIG11dGF0ZShleHAgPSBzdHJfc3BsaXQoZXhwLmZpZWxkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDFdKSAlPiUgc3BsaXQoLiRleHApCiAgZmlsdGVyKGV4cCA9PSAiMjBtaW4iKQpgYGAKCkFkZGluZyB0aGUgZ2ZwLnN1bSBjb2x1bW4gZm9yIHRoZSBzdGFibGUgR0ZQIGV4cGVyaW1lbnQKYGBge3J9CnB1cDEuY2VsbC5hdHRyIDwtIHJlYWRfY3N2KCJ+L3Bsb3RzL3B1cDEtcmZwLWdmcC1kZWNheS80LTI4LTIxLThockdGUC9kYXRhL2dmcF9zdGFibGVfZmlsdGVyZWQuY3N2IikgJT4lIAogIGZpbHRlcihpbWFnZS5ubyA9PSAxKSAlPiUgCiAgZHBseXI6OnNlbGVjdChjZWxsLmlkLCBnZnBTdW1CZ0FGc3ViKSAlPiUgCiAgbXV0YXRlKGNlbGwuaWQgPSBwYXN0ZTAoY2VsbC5pZCwiXyIsInN0YWJsZV9wdXAxLXJmcF9ub25lIikpICU+JSAKICBkcGx5cjo6cmVuYW1lKCJnZnAuc3VtLmJnLmFmLnN1YiIgPSAiZ2ZwU3VtQmdBRnN1YiIpICU+JSAKICBsZWZ0X2pvaW4ocHVwMS5jZWxsLmF0dHIgJT4lIAogICAgICAgICAgICAgIGZpbHRlcihkZWdyb24gPT0gInN0YWJsZSIpICU+JSAKICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KC1nZnAuc3VtLmJnLmFmLnN1YiksLiwgYnkgPSAiY2VsbC5pZCIpICU+JSAKICBiaW5kX3Jvd3MocHVwMS5jZWxsLmF0dHIgJT4lIAogICAgICAgICAgICAgIGZpbHRlcihkZWdyb24gIT0gInN0YWJsZSIpLC4pCmBgYAoKcmVtb3ZpbmcgbXVsdGlwbGUgZW50cmllcyBvZiB0aGUgY2VsbCBiZWNhdXNlIHNvbWUgY2VsbCBoYXZlIG1vcmUgdGhhbiBvbmUsIApgYGB7cn0KbXVsdGlwbGUucHVwMSA8LSBwdXAxLmNlbGwuYXR0ciAlPiUgCiAgbXV0YXRlKGRhcGkubWVhbi5iZy5zdWIucHVuY3RhID0gaWZlbHNlKGlzLm5hKGRhcGkubWVhbi5iZy5zdWIucHVuY3RhKSwgMCwgZGFwaS5tZWFuLmJnLnN1Yi5wdW5jdGEpICwgCiAgICAgICAgIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEgPSBpZmVsc2UoaXMubmEocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSksIDAgLCByZnAubWVhbi5iZy5zdWIucHVuY3RhKSkgJT4lIAogIGZpbHRlcihyZnAubWVhbi5iZy5zdWIucHVuY3RhID4gMCkgJT4lIAogIGdyb3VwX2J5KGNlbGwuaWQpICU+JSAKICB0YWxseSgpICU+JSAKICBmaWx0ZXIobj4xKQoKcHVwMS5jZWxsLmF0dHI8LSBwdXAxLmNlbGwuYXR0ciAlPiUgCiAgZ3JvdXBfYnkoY2VsbC5pZCkgJT4lIAogIG11dGF0ZShyZnAubWVhbi5iZy5zdWIucHVuY3RhID0gaWZlbHNlKGNlbGwuaWQgJWluJSBtdWx0aXBsZS5wdXAxJGNlbGwuaWQgLCBtZWFuKHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEpLCByZnAubWVhbi5iZy5zdWIucHVuY3RhKSwKICAgICAgICAgcmZwLnN1bS5iZy5zdWIucHVuY3RhID0gaWZlbHNlKGNlbGwuaWQgJWluJSBtdWx0aXBsZS5wdXAxJGNlbGwuaWQsIHN1bShyZnAubWVhbi5iZy5zdWIucHVuY3RhKSwgcmZwLnN1bS5iZy5zdWIucHVuY3RhKSkgJT4lIAogICAgZGlzdGluY3QoY2VsbC5pZCwgLmtlZXBfYWxsID0gVFJVRSkgCiAgCmBgYAoKI3Byb3RlYXNvbWUgaW5oaWJpdGlvbiBleHBlcmltZW50cwpgYGB7cn0KcHJvdEluaGkuYXR0ciA8LSByZWFkX2Nzdigifi9wbG90cy9hbGxfZGF0YS9hbGxfbWcxMzVfYXR0ci5jc3YiKSAlPiUgCiAgcmVuYW1lKCJjZWxsLmlkIiA9ICJ1bmlxdWUudHJhY2tJRCIpICU+JSAKICBmaWx0ZXIodGltZXBvaW50ID09IDEpICU+JSAKICBtdXRhdGUoY2VsbC5pZCA9IHBhc3RlMChjZWxsLmlkICwiXyIsZGVncm9uLCJfIixyZWQsIl8iLHRyZWF0bWVudCkpICU+JSAKICBtdXRhdGUoZXhwLmZpZWxkID0gcGFzdGUwKHN0cl9zcGxpdChjZWxsLmlkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDJdLCJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9zcGxpdChjZWxsLmlkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDNdKSwKICAgIGNvbG9ueSA9IGNhc2Vfd2hlbihleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zMyIsICIyMG1pbl9zNCIpIH4gIlJlcGxpY2F0ZSAxIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNSIsICIyMG1pbl9zNiIpIH4gIlJlcGxpY2F0ZSAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3M3IiwgIjIwbWluX3M4IiAsICIyMG1pbl9zOSIpIH4gIlJlcGxpY2F0ZSAzIikpCgptdWx0aXBsZS5wcm9JbmggPC0gcHJvdEluaGkuYXR0ciAlPiUgCiAgbXV0YXRlKGRhcGkubWVhbi5iZy5zdWIucHVuY3RhID0gaWZlbHNlKGlzLm5hKGRhcGkubWVhbi5iZy5zdWIucHVuY3RhKSwgMCwgZGFwaS5tZWFuLmJnLnN1Yi5wdW5jdGEpICwgCiAgICAgICAgIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEgPSBpZmVsc2UoaXMubmEocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSksIDAgLCByZnAubWVhbi5iZy5zdWIucHVuY3RhKSkgJT4lIAogIGZpbHRlcihyZnAubWVhbi5iZy5zdWIucHVuY3RhID4gMCkgJT4lIAogIGdyb3VwX2J5KGNlbGwuaWQpICU+JSAKICB0YWxseSgpICU+JSAKICBmaWx0ZXIobj4xKQoKcHJvdEluaGkuYXR0ciA8LSBwcm90SW5oaS5hdHRyICU+JSAKICBncm91cF9ieShjZWxsLmlkKSAlPiUgCiAgbXV0YXRlKHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEgPSBpZmVsc2UoY2VsbC5pZCAlaW4lIG11bHRpcGxlLnByb0luaCRjZWxsLmlkICwgbWVhbihyZnAubWVhbi5iZy5zdWIucHVuY3RhKSwgcmZwLm1lYW4uYmcuc3ViLnB1bmN0YSksCiAgICAgICAgIHJmcC5zdW0uYmcuc3ViLnB1bmN0YSA9IGlmZWxzZShjZWxsLmlkICVpbiUgbXVsdGlwbGUucHJvSW5oJGNlbGwuaWQsIHN1bShyZnAubWVhbi5iZy5zdWIucHVuY3RhKSwgcmZwLnN1bS5iZy5zdWIucHVuY3RhKSkgJT4lIAogICAgZGlzdGluY3QoY2VsbC5pZCwgLmtlZXBfYWxsID0gVFJVRSkgIAogIApgYGAKCkFkZGluZyB0aGUgcHJvdGVpbiBpbmhpYml0aW9uIGV4cGVyaW1lbnQgZGF0YQpgYGB7cn0KcHVwMS5wcm9JbmhpLmF0dHIgPC0gcHVwMS5jZWxsLmF0dHIgJT4lIAogIGJpbmRfcm93cyguLHByb3RJbmhpLmF0dHIgJT4lIAogICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoLXRpbWUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgLXRpbWVwb2ludCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC1pbWFnZS5ubywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAtbG4uZ2ZwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC1sbi5nZnAuZGlmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgLXRyYWNrSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAtZ2ZwLmludGVuc2l0eS5jZW50ZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAtZ2ZwLmludC5tZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgLWdmcC5pbnQubWVkaWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtZ2ZwLmludC5zdW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1uby5vZi50cmlhbmdsZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1maWVsZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLXRpbWUuZGlmLmdmcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLXJlYWwudGltZS5nZnAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1zYW1wbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1hdmcuZ2ZwLmJnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtTWluX2dmcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLWdmcC5tZWFuLmJnLnN1YiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLXZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtdDgwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtdDk1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAtdGhyZXNob2xkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtdGhyZXNob2xkXzk1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAtZ2ZwLm1lYW4uYmcuYWYuc3ViLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtdGhyZXNob2xkXzgwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtTWVhbl9nZnAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1pbWFnZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLWV4cGVyaW1lbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1nZnAuc3VtLmJnLnN1YikpCmBgYAoKCiNrZWVwaW5nIHRoZSBwYXJhbWV0ZXJzIGVzdGltYXRlZCBmcm9tIHRoZSAyLXBhcmFtZXRlciB3aXRoIG1hdHVyYXRpb24gbW9kZWwKYGBge3J9CiNvbmx5IGR5LmRtCmR5LnB1cDEucmVwMS5tYXQgPC0gYWljLmRmICU+JSAKICBmaWx0ZXIocmVkID09ICJwdXAxLXJmcCIpICU+JSAKICBmaWx0ZXIoaWZlbHNlKGRlZ3JvbiAlaW4lIGMoInN0YWJsZSIsInN0YWJsZS4yIiwic3RhYmxlLjMiKSwgZHkgPCAwLjEsIGR5IDwgMC41KSkgJT4lIAogIGdyb3VwX2J5KGNlbGwuaWQpICU+JSAKICBmaWx0ZXIobW9kZWwgPT0gImR5LmRtIikgJT4lIAogIG11dGF0ZShkbSA9IGlmZWxzZShpcy5uYShkbSksIEluZiwgZG0pKSAlPiUKICBmaWx0ZXIoIGRtID4gMC4wMDAwMTUpCmBgYAoKI2NvdW50IHRoZSBudW1iZXIgb2YgY2VsbHMgaW4gZWFjaCBleHBlcmltZW50IApgYGB7cn0KZHkucHVwMS5yZXAxLm1hdCAlPiUgZ3JvdXBfYnkoZGVncm9uLCB0cmVhdG1lbnQpICU+JSB0YWxseSgpCmBgYAojY3JlYXRpbmcgdGhlIGRmIGZvciB0aGUgTUxSCmBgYHtyfQptbHIuZGYgPC0gZHkucHVwMS5yZXAxLm1hdCAlPiUgCiAgI2xlZnQgam9pbiB3aXRoIHRoZSBkZiB3aXRoIGNlbGx1bGFyIGF0dHJpYnV0ZXMKICBsZWZ0X2pvaW4oLixwdXAxLnByb0luaGkuYXR0ciwgYnkgPSBjKCJjZWxsLmlkIiwicmVkIiwidHJlYXRtZW50IiwiZGVncm9uIiwgImV4cC5maWVsZCIsImNvbG9ueSIpKSAlPiUgCiAgI3JlbW92ZSBjZWxscyB3aXRoIG5vIHJmcCBwdW5jdGEgaW5mbyAKICBtdXRhdGUocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSA9IGlmZWxzZShpcy5uYShyZnAubWVhbi5iZy5zdWIucHVuY3RhKSwgMCwgcmZwLm1lYW4uYmcuc3ViLnB1bmN0YSkpICU+JSAKICBmaWx0ZXIocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSA+IDApCmBgYAoKI2NoZWNraW5nIGhvdyBtYW55IGNlbGxzIHRoZXJlIGFyZSBpbiBlYWNoIGV4cGVyaW1lbnQgCmBgYHtyfQptbHIuZGYgJT4lIGdyb3VwX2J5KGRlZ3JvbiwgdHJlYXRtZW50KSAlPiUgdGFsbHkoKQpgYGAKCiMjUmVtb3ZpbmcgdGhlIGNvbHVtbnMgdGhhdCBJIHdvbnQgcmVncmVzcyB1cG9uCmBgYHtyfQptbHIuZGYgPC0gbWxyLmRmICU+JSAKICBmaWx0ZXIocG9zLnggPiA0NSAmIHBvcy54IDwgMTE1MCwKICBwb3MueSA+IDQ1ICYgcG9zLnkgPCAxMDAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1mLCAKICAgICAgICAgLXJmcC5tZWFuLmFmLnN1Yi5wdW5jdGEsCiAgICAgICAgIC1yZnAuc3VtLmFmLnN1Yi5wdW5jdGEsIAogICAgICAgICAtZGFwaS5zdW0uYWYuc3ViLnB1bmN0YSwKICAgICAgICAgLWRhcGkubWVhbi5hZi5zdWIucHVuY3RhLAogICAgICAgICAtbW9kZWwsIAogICAgICAgICAtaywKICAgICAgICAgLWZldmFscywKICAgICAgICAgLWdldmFscywgCiAgICAgICAgIC1uaXRlciwgCiAgICAgICAgIC1jb252Y29kZSwgCiAgICAgICAgIC1ra3QxLAogICAgICAgICAta2t0MiwKICAgICAgICAgLXZhbHVlLAogICAgICAgICAteHRpbWUsIAogICAgICAgICAjIC10cmVhdG1lbnQsCiAgICAgICAgIC1yZnAubWVhbi5iZy5zdWIsCiAgICAgICAgIC1yZnAuc3VtLmJnLnN1YiwKICAgICAgICAgLWRhcGkubWVhbi5iZy5zdWIsCiAgICAgICAgIC1kYXBpLnN1bS5iZy5zdWIsCiAgICAgICAgIC1kYXBpLm1lYW4uYmcuc3ViLnB1bmN0YSwKICAgICAgICAgLWFyZWEucHVuY3RhLAogICAgICAgICAtQkJfQiwKICAgICAgICAgLUJCX0MsCiAgICAgICAgIC1wb3MueCwKICAgICAgICAgLXBvcy55LAogICAgICAgICAtZ2ZwLnN1bS5iZy5hZi5zdWIsCiAgICAgICAgIC1yZnAuc3VtLmJnLnN1Yi5wdW5jdGEsCiAgICAgICAgIC1uby5vZi52b3hlbHMsCiAgICAgICAgIC12b2x1bWUsCiAgICAgICAgIC1zcGhlcmFjaXR5KSAlPiUgCiAgbXV0YXRlKHNoYXBlID0gRWxpcF9CL0VsaXBfQywgCiAgICAgICAgIHQuaGFsZiA9IGxvZygyKS9keSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGRwbHlyOjpzZWxlY3QoLWNlbGwuaWQsIAogICAgICAgICAgICAgICAgLXJlZCwKICAgICAgICAgICAgICAgIC1leHAuZmllbGQsIAogICAgICAgICAgICAgICAgLWFpYywKICAgICAgICAgICAgICAgIC1FbGlwX0IsCiAgICAgICAgICAgICAgICAtRWxpcF9DLCAKICAgICAgICAgICAgICAgIC1leHApIApgYGAKCiNSZWdyZXNzb3JzIHRvIHVzZSBmb3IgTUxSCmBgYHtyfQpyZWdyZXNzb3JzIDwtIGMoImRtIiwKICAgICAgICAgICAgICAgICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiwKICAgICAgICAgICAgICAgICJhcmVhIiwKICAgICAgICAgICAgICAgICJyZnAubWVhbi5iZy5zdWIucHVuY3RhIiwKICAgICAgICAgICAgICAgICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiwKICAgICAgICAgICAgICAgICJzaGFwZSIpCmBgYAoKCiNkZiB3aGVyZSB0aGUgdHdvIGV4cGVyaW1lbnRzIG9mIGNsbjIgYW5kIHN0YWJsZS1HRlAgYXJlIGNsdWJiZWQgCmBgYHtyfQptbHIuZGYyIDwtIG1sci5kZiAlPiUgCiAgZmlsdGVyKGRlZ3JvbiAlaW4lIGMoImNsbjIuMyIsIm1PREMuMiIsInN0YWJsZS4zIiwic3RhYmxlLjIiLCJjbG4yLjQiKSkgJT4lIAogIG11dGF0ZShkZWdyb24gPSBjYXNlX3doZW4oZGVncm9uICVpbiUgYygiY2xuMi4zIiwiY2xuMi4yIiwiY2xuMiIsImNsbjIuNCIpIH4gInllR0ZQLUNMTjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVncm9uICVpbiUgYygibU9EQy4yIiwgIm1PREMiKSAgfiAieWVHRlAtbU9EQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWdyb24gJWluJSBjKCJzdGFibGUiLCJzdGFibGUuMiIsInN0YWJsZS4zIikgfiAieWVHRlAiKSkgCiAgCmBgYAoKCiNkZiB0byBiZSB1c2VkIHdpdGggc3RlcCBmdW5jdGlvbgpgYGB7cn0KdGVtcC5kZi5saXN0IDwtIG1sci5kZjIgJT4lIAogICAgZmlsdGVyKHRyZWF0bWVudCA9PSAibm9uZSIpICU+JSAgCiAgIyBtdXRhdGUoIGRtID0gbG9nMTAoZG0pKSAlPiUgCiAgc3BsaXQoLiRkZWdyb24pCmBgYAoKCiN1c2luZyBzdGVwQUlDIGZyb20gTUFTUwpgYGB7cn0KbGlicmFyeShNQVNTKQoKZnVsbC5zdGVwQUlDLm1hc3MgPC0gbGFwcGx5KHRlbXAuZGYubGlzdCwgZnVuY3Rpb24oYSl7CiAgbiA8LSBucm93KGEpCiAgbG0ub2JqIDwtIGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBhICU+JSAKICAgICBkcGx5cjo6c2VsZWN0KHJlZ3Jlc3NvcnMsCiAgICAgICAgICAgICAgICAgICB0LmhhbGYsCiAgICAgICAgICAgICAgICAgICAtZHksIAogICAgICAgICAgICAgICAgICAgLXRyZWF0bWVudCkpCiAgICAgCiBzdGVwQUlDKG9iamVjdCA9IGxtLm9iaiwgCiAgICAgZGlyZWN0aW9uID0gImJhY2t3YXJkIiwgCiAgICAgdHJhY2UgPSBUKQp9KQpgYGAKCiNzdGVwIEFJQyB3aXRoIGFsbCB0aGUgZnAgbWFya2VycyArIGNlbGwgc2hhcGUgCmBgYHtyfQpmdWxsLnN0ZXBBSUMgPC0gbGFwcGx5KHRlbXAuZGYubGlzdCwgZnVuY3Rpb24oYSl7CiAgbiA8LSBucm93KGEpCiBzdGVwKGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBhICU+JSAKICAgICBkcGx5cjo6c2VsZWN0KHJlZ3Jlc3NvcnMsCiAgICAgICAgICAgICAgICAgICB0LmhhbGYsCiAgICAgICAgICAgICAgICAgICAtZHksIAogICAgICAgICAgICAgICAgICAgLXRyZWF0bWVudCkpLCAKICAgICBkaXJlY3Rpb24gPSAiYmFja3dhcmQiLCAKICAgICB0cmFjZSA9IFQsCiAgICAgIyBrID0gbG9nKG4pLAogICAgIGsgPTIgKSAjayA9IDIgd2hlbiBzbWFsbCBkYXRhc2V0IGFuZCBrID0gbG9nKG4pIHdoZXJlIG4gPSBuby4gb2Ygb2JzZXJ2YXRpb25zIGZvciB3aGVuIHRoZSBkYXRhc2V0IGlzIGxhcmdlCn0pCgoKYGBgCgoKI3N0ZXAgQUlDIHdpdGggb25seSB0aGUgZmx1b3Jlc2NlbnQgbWFya2VycyAKYGBge3J9CmZ1bGwuc3RlcEFJQy5mcCA8LSBsYXBwbHkodGVtcC5kZi5saXN0LCBmdW5jdGlvbihhKXsKICBuIDwtIG5yb3coYSkKIHN0ZXAobG0odC5oYWxmIH4gLiwgZGF0YSA9IGEgJT4lIAogICAgIGRwbHlyOjpzZWxlY3QocmVncmVzc29ycy5mcCwKICAgICAgICAgICAgICAgICAgIHQuaGFsZiwKICAgICAgICAgICAgICAgICAgIC1keSwgCiAgICAgICAgICAgICAgICAgICAtdHJlYXRtZW50KSksIAogICAgIGRpcmVjdGlvbiA9ICJiYWNrd2FyZCIsIAogICAgIHRyYWNlID0gVCwKICAgICBrID0gMikKfSkKCmBgYAoKVmFyaWFuY2UgaW4gdC1oYWxmIGV4cGxhaW5lZCBieSBlYWNoIHJlZ3Jlc3Nvcgp1c2luZyBhbm92YQoKYGBge3J9CnZhci5leHBsYWluZWQgPC0gZnVsbC5zdGVwQUlDICU+JSAKICBtYXAoLiwgYW5vdmEgJT4lIGFzLmRhdGEuZnJhbWUpICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gInNhbXBsZSIpICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInByZWRpY3RvciIpICU+JSAKICAjIGZpbHRlcihzYW1wbGUgJWluJSBjKCJtT0RDLjIiLCJjbG4yLjMiLCJjbG4yLjQiLCJzdGFibGUuMiIsInN0YWJsZS4zIikpICU+JSAKICBncm91cF9ieShzYW1wbGUpICU+JSAKICBtdXRhdGUodmFyLmV4cCA9ICh2YWx1ZS5TdW0uU3Evc3VtKHZhbHVlLlN1bS5TcSkpKjEwMCwgCiAgICAgICAgIHByZWRpY3RvciA9IHN0cl9zcGxpdChwcmVkaWN0b3IsIHBhdHRlcm4gPSAiXFwuXFwuXFwuIiwgc2ltcGxpZnkgPSBUKVssMV0sIAogICAgICAgICBwcmVkaWN0b3IgPSBjYXNlX3doZW4ocHJlZGljdG9yID09ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiB+ICJHRlAiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3RvciA9PSAiYXJlYSIgfiAiQXJlYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkaWN0b3IgPT0gInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiIH4gIlB1cDEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdG9yID09ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiB+ICJETkEiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3RvciA9PSAic2hhcGUiIH4gIlNoYXBlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkaWN0b3IgPT0gImRtIiB+ICJSYXRlIG9mIE1hdHVyYXRpb24iCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRX5wcmVkaWN0b3IpKSAlPiUgCiAgc3BsaXQoLiRzYW1wbGUpCgp2YXIuZXhwbGFpbmVkCmBgYAoKI3Bsb3R0aW5nIHRoZSB2YXJpYW5jZSBleHBsYWluZWQgCmBgYHtyfQpyZW1haW4ucmVnIDwtIGRhdGEuZnJhbWUoc2FtcGxlID0gYygieWVHRlAtQ0xOMiIsInllR0ZQLUNMTjIiLCJ5ZUdGUCIsInllR0ZQIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdG9yID0gYygiUmF0ZSBvZiBNYXR1cmF0aW9uIiwgIlNoYXBlIiwiU2hhcGUiLCJQdXAxIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgdmFyLmV4cCA9IHJlcCgwLDQpLAogICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUuUHIuLkYuID0gcmVwKDAsNCkpCnZhci5leHAucGx0IDwtIHZhci5leHBsYWluZWQgJT4lIAogIGJpbmRfcm93cygpICU+JSAKICBiaW5kX3Jvd3MoLixyZW1haW4ucmVnKSAlPiUgCiAgZmlsdGVyKHByZWRpY3RvciAhPSAiUmVzaWR1YWxzIikgJT4lIAogIGRwbHlyOjpzZWxlY3Qoc2FtcGxlLCBwcmVkaWN0b3IsIHZhci5leHAsdmFsdWUuUHIuLkYuKSAlPiUgCiAgbXV0YXRlKHNhbXBsZSA9IGZhY3RvcihzYW1wbGUgLCBsZXZlbHMgPSBjKCJ5ZUdGUC1tT0RDIiwieWVHRlAtQ0xOMiIsInllR0ZQIikpKSAlPiUgCiAgIyBtdXRhdGUodmFyLnBhbCA9IGlmZWxzZSh2YWx1ZS5Qci4uRi4gPCAwLjA1LCAiPDAuMDUiLCI+MC4wNSIpKSAlPiUgCiAgYXJyYW5nZShzYW1wbGUpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IHByZWRpY3RvciwgeSA9IHZhci5leHAgKSkrCiAgZ2VvbV9jb2wod2lkdGggPSAwLjUpKwogIGZhY2V0X3dyYXAofnNhbXBsZSwgc2NhbGVzID0gImZyZWUiKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHN0cl93cmFwKHgsIHdpZHRoID0gNSkpKwogIHRoZW1lX3B1YnIoKSsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDAuMSksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkrCiAgeWxpbSgwLDIwKSsKICB5bGFiKCJWYXJpYW5jZSBleHBsYWluZWQgKCUpIikrCiAgeGxhYigiQ2VsbHVsYXIgZmVhdHVyZXMiKSsKICBsYWJzKHRpdGxlID0gIkIiKQp2YXIuZXhwLnBsdApgYGAKCgojcGxvdHM6IApgYGB7cn0KZ2ZwLjYuY29yLnBsdCA8LSBtbHIuZGYgJT4lCiAgbXV0YXRlKGRtID0gbG9nMTAoZG0pKSAlPiUgCiAgZmlsdGVyKGRlZ3JvbiAlaW4lIGMoIm1PREMuMiIsICJjbG4yLjMiLCAiY2xuMi40IiwgInN0YWJsZS4yIiwgInN0YWJsZS4zIikpICU+JQogIGRwbHlyOjpzZWxlY3QodC5oYWxmLAogICAgICAgICByZWdyZXNzb3JzLAogICAgICAgICBkZWdyb24pICU+JQogIHJlbmFtZSgKICAgICJHRlAiID0gImdmcC5tZWFuLmJnLmFmLnN1Yi5uZXciLAogICAgIlB1cDEtdERpbWVyIiA9ICJyZnAubWVhbi5iZy5zdWIucHVuY3RhIiwKICAgICJETkEiID0gImRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEiLAogICAgIkFyZWEiID0gImFyZWEiCiAgKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IDI6NykgJT4lCiAgbXV0YXRlKGRlZ3JvbiA9IGNhc2Vfd2hlbigKICAgICAgZGVncm9uICVpbiUgYygiY2xuMi4zIiwgImNsbjIuMiIsICJjbG4yIiwgImNsbjIuNCIpIH4gInllR0ZQLUNMTjIiLAogICAgICBkZWdyb24gJWluJSBjKCJtT0RDLjIiLCAibU9EQyIpICB+ICJ5ZUdGUC1tT0RDIiwKICAgICAgZGVncm9uICVpbiUgYygic3RhYmxlIiwgInN0YWJsZS4yIiwgInN0YWJsZS4zIikgfiAieWVHRlAiCiAgICApLAogICAgZGVncm9uID0gZmFjdG9yKGRlZ3JvbiAsIGxldmVscyA9IGMoInllR0ZQLW1PREMiLCAieWVHRlAtQ0xOMiIsICJ5ZUdGUCIpKQogICkgJT4lCiAgZmlsdGVyKCEobmFtZSAlaW4lIGMoInNoYXBlIiwiZG0iKSkpICU+JSAKICBnZ3Bsb3QoLiwgYWVzKHggPSB2YWx1ZSwgeSA9IHQuaGFsZikpICsKICAgICAgZ2dwb2ludGRlbnNpdHk6Omdlb21fcG9pbnRkZW5zaXR5KHNpemUgPSAwLjIsIGd1aWRlcyA9IEYpICsKICAgICAgc3RhdF9jb3Ioc2l6ZSA9IDIpICsKICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkNCIsIHNpemUgPSAwLjUpKwogICAgICBmYWNldF93cmFwKGRlZ3JvbiB+IG5hbWUsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDQpICsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIGxhYnMoeCA9IE5VTEwpICsKICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzApLAogICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDIsIm1tIiksIAogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDAuMSkpKwogIHlsYWIoIkhhbGYtbGlmZSBbbWluLl0iKSsKICB4bGFiKCJBLlUiKSsKICBsYWJzKHRpdGxlID0gIkEiKQogIApnZnAuNi5jb3IucGx0CmBgYAp3aXRoIHByb3RlaW4gaW5oaWJpdGlvbgpgYGB7cn0KIG1sci5kZiAlPiUKICBtdXRhdGUoZG0gPSBsb2cxMChkbSkpICU+JSAKICBmaWx0ZXIoZGVncm9uICVpbiUgYygibU9EQyIpKSAlPiUKICAjIGZpbHRlcighKHRyZWF0bWVudCAlaW4lIGMoIm5vbmUiLCAiZG1zbzEiLCI1MHVNIikpLCAKICAgICAgICAgIyBpZmVsc2UodHJlYXRtZW50ID09ICI1dU0iLCB0LmhhbGYgPCAxMzguNjI5NCwgdC5oYWxmID09IHQuaGFsZikpICU+JSAgCiAgZHBseXI6OnNlbGVjdCh0LmhhbGYsCiAgICAgICAgIHJlZ3Jlc3NvcnMsCiAgICAgICAgIGRlZ3JvbiwKICAgICAgICAgdHJlYXRtZW50KSAlPiUKICByZW5hbWUoCiAgICAiR0ZQIiA9ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiwKICAgICJQdXAxLXREaW1lciIgPSAicmZwLm1lYW4uYmcuc3ViLnB1bmN0YSIsCiAgICAiRE5BIiA9ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiwKICAgICJBcmVhIiA9ICJhcmVhIgogICkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAyOjcpICU+JQogIG11dGF0ZShkZWdyb24gPSBjYXNlX3doZW4oCiAgICBkZWdyb24gJWluJSBjKCJtT0RDIikgIH4gInllR0ZQLW1PREMiKSwKICAgIHRyZWF0bWVudCA9IGZhY3Rvcih0cmVhdG1lbnQsIGxldmVscyA9IGMoIm5vbmUiLCJkbXNvMSIsImRtc28yIiwiMXVNIiwiMi41dU0iLCI1dU0iLCI1MHVNIikpKSAlPiUKICBmaWx0ZXIoIShuYW1lICVpbiUgYygic2hhcGUiLCJkbSIpKSwKICAgICAgICAgISh0cmVhdG1lbnQgJWluJSBjKCJub25lIiwiZG1zbzEiLCI1MHVNIikpLCAKICAgICAgICAgdC5oYWxmIDwgMTMwKSAlPiUgCiAgCiAgZ2dwbG90KC4sIGFlcyh4ID0gdmFsdWUsIHkgPSB0LmhhbGYpKSArCiAgICAgIGdncG9pbnRkZW5zaXR5OjpnZW9tX3BvaW50ZGVuc2l0eShzaXplID0gMC4yLCBndWlkZXMgPSBGKSArCiAgICAgIHN0YXRfY29yKHNpemUgPSAyKSArCiAgICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZDQiLCBzaXplID0gMC41KSsKICAgICAgZmFjZXRfZ3JpZCh0cmVhdG1lbnQgfiBuYW1lLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIGxhYnMoeCA9IE5VTEwpICsKICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzApLAogICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDIsIm1tIiksIAogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKwogIHlsYWIoIkhhbGYtTGlmZSBbbWluLl0iKSsKICB4bGFiKCJBLlUiKQoKYGBgCgojc3RlcEFJQyB3aXRoIHByb3RlYXNvbWUgaW5oaWJpdGlvbiBleHBlcmltZW50cwpXaXRoIGFsbCBmcCByZWdyZXNzb3JzCmBgYHtyfQp0ZW1wLmRmLmxpc3QuZG1zbyA8LSBtbHIuZGYgJT4lIAogICAgZmlsdGVyKHRyZWF0bWVudCAhPSAibm9uZSIsIHQuaGFsZiA8IDEzMCkgJT4lICAKICBzcGxpdCguJHRyZWF0bWVudCkKCmZ1bGwuc3RlcEFJQy5mcC5kbXNvIDwtIGxhcHBseSh0ZW1wLmRmLmxpc3QuZG1zbywgZnVuY3Rpb24oYSl7CiBzdGVwKGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBhICU+JSAKICAgICBkcGx5cjo6c2VsZWN0KHJlZ3Jlc3NvcnMuZnAsCiAgICAgICAgICAgICAgICAgICB0LmhhbGYsCiAgICAgICAgICAgICAgICAgICAtZHksIAogICAgICAgICAgICAgICAgICAgLXRyZWF0bWVudCkpLCAKICAgICBkaXJlY3Rpb24gPSAiYmFja3dhcmQiLCB0cmFjZSA9IFQpCn0pCgpgYGAKCndpdGggZnAgcmVncmVzc29ycyArIGNlbGx1YXIgc2hhcGUgCmBgYHtyfQp0ZW1wLmRmLmxpc3QuZG1zbyA8LSBtbHIuZGYgJT4lIAogICAgZmlsdGVyKHRyZWF0bWVudCAhPSAibm9uZSIsIHQuaGFsZiA8IDEzMCkgJT4lICAKICBzcGxpdCguJHRyZWF0bWVudCkKCmZ1bGwuc3RlcEFJQy5kbXNvIDwtIGxhcHBseSh0ZW1wLmRmLmxpc3QuZG1zbywgZnVuY3Rpb24oYSl7CiBzdGVwKGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBhICU+JSAKICAgICBkcGx5cjo6c2VsZWN0KHJlZ3Jlc3NvcnMuZnAsCiAgICAgICAgICAgICAgICAgICB0LmhhbGYsCiAgICAgICAgICAgICAgICAgICAtZHksIAogICAgICAgICAgICAgICAgICAgLXRyZWF0bWVudCkpLCAKICAgICBkaXJlY3Rpb24gPSAiYmFja3dhcmQiLCB0cmFjZSA9IFQpCn0pCgoKYGBgCgpWYXJpYW5jZSBpbiB0LWhhbGYgZXhwbGFpbmVkIGJ5IGVhY2ggcmVncmVzc29yCmBgYHtyfQpmdWxsLnN0ZXBBSUMuZG1zbyAlPiUgCiAgbWFwKC4sIGFub3ZhICU+JSBhcy5kYXRhLmZyYW1lKSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJzYW1wbGUiKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJwcmVkaWN0b3IiKSAlPiUgCiAgIyBmaWx0ZXIoc2FtcGxlICVpbiUgYygibU9EQy4yIiwiY2xuMi4zIiwiY2xuMi40Iiwic3RhYmxlLjIiLCJzdGFibGUuMyIpKSAlPiUgCiAgZ3JvdXBfYnkoc2FtcGxlKSAlPiUgCiAgbXV0YXRlKHZhci5leHAgPSAodmFsdWUuU3VtLlNxL3N1bSh2YWx1ZS5TdW0uU3EpKSoxMDApICU+JSAKICBzcGxpdCguJHNhbXBsZSkKCmZ1bGwuc3RlcEFJQy5mcC5kbXNvICU+JSAKICBtYXAoLiwgYW5vdmEgJT4lIGFzLmRhdGEuZnJhbWUpICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gInNhbXBsZSIpICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInByZWRpY3RvciIpICU+JSAKICAjIGZpbHRlcihzYW1wbGUgJWluJSBjKCJtT0RDLjIiLCJjbG4yLjMiLCJjbG4yLjQiLCJzdGFibGUuMiIsInN0YWJsZS4zIikpICU+JSAKICBncm91cF9ieShzYW1wbGUpICU+JSAKICBtdXRhdGUodmFyLmV4cCA9ICh2YWx1ZS5TdW0uU3Evc3VtKHZhbHVlLlN1bS5TcSkpKjEwMCkgJT4lIAogIHNwbGl0KC4kc2FtcGxlKQoKYGBgCgpgYGB7cn0KZnVsbC5zdGVwQUlDLmRtc28gJT4lIAogIG1hcCguLCBhbm92YSAlPiUgYXMuZGF0YS5mcmFtZSkgJT4lIAogIGJpbmRfcm93cyguaWQgPSAic2FtcGxlIikgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAicHJlZGljdG9yIikgJT4lIAogICMgZmlsdGVyKHNhbXBsZSAlaW4lIGMoIm1PREMuMiIsImNsbjIuMyIsImNsbjIuNCIsInN0YWJsZS4yIiwic3RhYmxlLjMiKSkgJT4lIAogIGdyb3VwX2J5KHNhbXBsZSkgJT4lIAogIG11dGF0ZSh2YXIuZXhwID0gKHZhbHVlLlN1bS5TcS9zdW0odmFsdWUuU3VtLlNxKSkqMTAwLCAKICAgICAgICAgcHJlZGljdG9yID0gc3RyX3NwbGl0KHByZWRpY3RvciwgcGF0dGVybiA9ICJcXC5cXC5cXC4iLCBzaW1wbGlmeSA9IFQpWywxXSwgCiAgICAgICAgIHByZWRpY3RvciA9IGNhc2Vfd2hlbihwcmVkaWN0b3IgPT0gImdmcC5tZWFuLmJnLmFmLnN1Yi5uZXciIH4gIkdGUCIgLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdG9yID09ICJhcmVhIiB+ICJBcmVhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3RvciA9PSAicmZwLm1lYW4uYmcuc3ViLnB1bmN0YSIgfiAiUHVwMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkaWN0b3IgPT0gImRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEiIH4gIkROQSIgLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdG9yID09ICJzaGFwZSIgfiAiU2hhcGUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3RvciA9PSAiZG0iIH4gIlJhdGUgb2YgTWF0dXJhdGlvbiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFfnByZWRpY3RvcikpICU+JSAKICBzcGxpdCguJHNhbXBsZSkKYGBgCgpgYGB7cn0KbWxyLmRmICU+JQogIG11dGF0ZShkbSA9IGxvZzEwKGRtKSkgJT4lIAogIGZpbHRlcihkZWdyb24gJWluJSBjICgibU9EQyIpICkgJT4lCiAgZmlsdGVyKCEodHJlYXRtZW50ICVpbiUgYygibm9uZSIsICJkbXNvMSIsIjUwdU0iKSksIAogICAgICAgICBpZmVsc2UodHJlYXRtZW50ID09ICI1dU0iLCB0LmhhbGYgPCAxMzguNjI5NCwgdC5oYWxmID09IHQuaGFsZikpICU+JSAKICBkcGx5cjo6c2VsZWN0KHQuaGFsZiwKICAgICAgICAgcmVncmVzc29ycywKICAgICAgICAgZGVncm9uLAogICAgICAgICB0cmVhdG1lbnQpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IGFyZWEsIHkgPSByZnAubWVhbi5iZy5zdWIucHVuY3RhKSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRikrCiAgZmFjZXRfd3JhcCh+dHJlYXRtZW50KSsKICBzdGF0X2NvcigpCmBgYAoKCiNnZ3BhaXJzIApgYGB7cn0KI3RvIGJlIHVzZWQgd2l0aCBnZ3BhaXJzCm15X2ZuIDwtIGZ1bmN0aW9uKGRhdGEsIG1hcHBpbmcsIC4uLil7CiAgcCA8LSBnZ3Bsb3QoZGF0YSA9IGRhdGEsIG1hcHBpbmcgPSBtYXBwaW5nKSArIAogICAgZ2dwb2ludGRlbnNpdHk6Omdlb21fcG9pbnRkZW5zaXR5KHNpemUgPSAwLjEpKwogICAgIyBnZW9tX3BvaW50KHNpemUgPSAwLjEsIGFscGhhID0gMC4xKSArIAogICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsICBjb2xvcj0icmVkNCIsIHNlID0gRkFMU0UsIGx3ZCA9IDAuNSkrCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCiAgcAp9CgpnZnAuYXJlYS5jb3IuZ2dQYWlyIDwtIG1sci5kZiAlPiUKICBmaWx0ZXIoZGVncm9uICVpbiUgYygibU9EQy4yIiwgImNsbjIuMyIsICJjbG4yLjQiLCAic3RhYmxlLjIiLCAic3RhYmxlLjMiKSkgJT4lCiAgZHBseXI6OnNlbGVjdCh0LmhhbGYsCiAgICAgICAgIHJlZ3Jlc3NvcnMsCiAgICAgICAgIGRlZ3JvbikgJT4lCiAgcmVuYW1lKAogICAgIkdGUCIgPSAiZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldyIsCiAgICAiUHVwMS10RGltZXIiID0gInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiLAogICAgIkROQSIgPSAiZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSIsCiAgICAiQXJlYSIgPSAiYXJlYSIKICApICU+JQogIGRwbHlyOjpzZWxlY3QoQXJlYSwgRE5BLCBgUHVwMS10RGltZXJgLEdGUCxkZWdyb24gKSAlPiUgCiAgbXV0YXRlKAogICAgZGVncm9uID0gY2FzZV93aGVuKAogICAgICBkZWdyb24gJWluJSBjKCJjbG4yLjMiLCAiY2xuMi40IikgfiAieWVHRlAtQ0xOMiIsCiAgICAgIGRlZ3JvbiAlaW4lIGMoIm1PREMuMiIpICB+ICJ5ZUdGUC1tT0RDIiwKICAgICAgZGVncm9uICVpbiUgYygic3RhYmxlLjIiLCAic3RhYmxlLjMiKSB+ICJ5ZUdGUCIKICAgICksCiAgICBkZWdyb24gPSBmYWN0b3IoZGVncm9uICwgbGV2ZWxzID0gYygieWVHRlAtbU9EQyIsICJ5ZUdGUC1DTE4yIiwgInllR0ZQIikpCiAgKSAlPiUKICBzcGxpdCguJGRlZ3JvbikgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYSAlPiUgCiAgICAgIGdncGFpcnMoLiwKICAgICAgICAgICMgbGVnZW5kID0gNSwKICAgICAgICAgIGNvbHVtbnMgPSAxOjQsCiAgICAgICAgICAjIG1hcHBpbmcgPSBnZ3Bsb3QyOjphZXMoY29sb3IgPSBSZXBsaWNhdGUpLAogICAgICAgICAgbG93ZXIgPSBsaXN0KGNvbnRpbnVvdXMgPSBteV9mbiwKICAgICAgICAgICAgICAgICAgICAgIGRpc2NyZXRlID0gImJsYW5rIiwgCiAgICAgICAgICAgICAgICAgICAgICBjb21ibz0iYmxhbmsiKSwgCiAgICAgICAgICAjIHVwcGVyID0gImJsYW5rIiwKICAgICAgICAgICMgZGlhZyA9IE5VTEwsCiAgICAgICAgICAgZGlhZyA9IGxpc3QoZGlzY3JldGU9ImJhckRpYWciLAogICAgICAgICAgICAgICAgICAgICAgY29udGludW91cyA9IHdyYXAoImRlbnNpdHlEaWFnIiwgYWxwaGE9MC41ICkpLAogICAgICAgICAgdXBwZXIgPSBsaXN0KGRpc2NyZXRlPSB3cmFwKCJiYXJEaWFnIiAsIG91dGxpZXIuc2l6ZSA9IDAuNSksCiAgICAgICAgICAgICAgICAgICAgICAgY29tYm8gPSB3cmFwKCJib3hfbm9fZmFjZXQiLCBvdXRsaWVyLnNpemUgPSAwLjUpLAogICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVvdXMgPSB3cmFwKCJjb3IiLCBkaXNwbGF5X2dyaWQgPSBGQUxTRSwgc2l6ZSA9IDIuNSAsIG1ldGhvZCA9ICJwZWFyc29uIiwgY29sb3IgPSAicmVkNCIpKSwKICAgICAgICAgIGxhYmVsbGVyID0gbGFiZWxfd3JhcF9nZW4od2lkdGggPSAyLCBtdWx0aV9saW5lID0gVFJVRSkpKwogIHRoZW1lX2J3KCkrCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCwgaGp1c3QgPSAxKSkrCiAgICAgIGxhYnModGl0bGUgPSBhJGRlZ3JvblsxXSkKICB9KQogIApnZnAuYXJlYS5jb3IuZ2dQYWlyCmBgYApgYGB7cn0KZ2dzYXZlKHBsb3QgPSBnZnAuYXJlYS5jb3IuZ2dQYWlyJGB5ZUdGUC1tT0RDYCwgZmlsZW5hbWUgPSAiZ2ZwX21PRENfNENvcl9nZ1AucG5nIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMy41KQoKZ2dzYXZlKHBsb3QgPSBnZnAuYXJlYS5jb3IuZ2dQYWlyJGB5ZUdGUC1tT0RDYCwgZmlsZW5hbWUgPSAiZ2ZwX21PRENfNENvcl9nZ1AucGRmIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMy41KQoKZ2dzYXZlKHBsb3QgPSBnZnAuYXJlYS5jb3IuZ2dQYWlyJGB5ZUdGUC1DTE4yYCwgZmlsZW5hbWUgPSAiZ2ZwX2NsbjJfNENvcl9nZ1AucG5nIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMy41KQoKZ2dzYXZlKHBsb3QgPSBnZnAuYXJlYS5jb3IuZ2dQYWlyJGB5ZUdGUC1DTE4yYCwgZmlsZW5hbWUgPSAiZ2ZwX2NsbjJfNENvcl9nZ1AucGRmIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMy41KQoKZ2dzYXZlKHBsb3QgPSBnZnAuYXJlYS5jb3IuZ2dQYWlyJGB5ZUdGUGAsIGZpbGVuYW1lID0gImdmcF80Q29yX2dnUC5wbmciLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA0LCBoZWlnaHQgPSAzLjUpCgpnZ3NhdmUocGxvdCA9IGdmcC5hcmVhLmNvci5nZ1BhaXIkYHllR0ZQYCwgZmlsZW5hbWUgPSAiZ2ZwXzRDb3JfZ2dQLnBkZiIsIHBhdGggPSAifi9wbG90cy9wYXBlcjEvZmlndXJlcy9maWdfMi8iLCB3aWR0aCA9IDQsIGhlaWdodCA9IDMuNSkKYGBgCgpgYGB7cn0KdGVzdC5nZ1AgPC0gKHdyYXBfZWxlbWVudHMoZ2dtYXRyaXhfZ3RhYmxlKGdmcC5hcmVhLmNvci5nZ1BhaXIkYHllR0ZQLW1PRENgKSl8d3JhcF9lbGVtZW50cyhnZ21hdHJpeF9ndGFibGUoZ2ZwLmFyZWEuY29yLmdnUGFpciRgeWVHRlAtQ0xOMmApKXwgd3JhcF9lbGVtZW50cyhnZ21hdHJpeF9ndGFibGUoZ2ZwLmFyZWEuY29yLmdnUGFpciR5ZUdGUCkpKSsKIHBsb3RfYW5ub3RhdGlvbih0YWdfbGV2ZWxzID0gIkEiKQpgYGAKCmBgYHtyfQpnZ3NhdmUocGxvdCA9IHRlc3QuZ2dQLCBmaWxlbmFtZSA9ICJ0ZXN0X2dnUC5wZGYiLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA2LjUsIGhlaWdodCA9IDMpCmBgYAoKI2FyZWEgdnMgcHVwMSB2cyBkbmEgdnMgZ2ZwCmBgYHtyfQpkZl9jb3JTdXBfZmlnIDwtIG1sci5kZiAlPiUKICBmaWx0ZXIoZGVncm9uICVpbiUgYygibU9EQy4yIiwgImNsbjIuMyIsICJjbG4yLjQiLCAic3RhYmxlLjIiLCAic3RhYmxlLjMiKSkgJT4lCiAgZHBseXI6OnNlbGVjdCh0LmhhbGYsCiAgICAgICAgIHJlZ3Jlc3NvcnMsCiAgICAgICAgIGRlZ3JvbikgJT4lCiAgcmVuYW1lKAogICAgIkdGUCIgPSAiZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldyIsCiAgICAiUHVwMS10RGltZXIiID0gInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiLAogICAgIkROQSIgPSAiZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSIsCiAgICAiQXJlYSIgPSAiYXJlYSIKICApICU+JQogIGRwbHlyOjpzZWxlY3QoQXJlYSwgRE5BLCBgUHVwMS10RGltZXJgLEdGUCxkZWdyb24gKSAlPiUgCiAgbXV0YXRlKAogICAgZGVncm9uID0gY2FzZV93aGVuKAogICAgICBkZWdyb24gJWluJSBjKCJjbG4yLjMiLCAiY2xuMi40IikgfiAieWVHRlAtQ0xOMiIsCiAgICAgIGRlZ3JvbiAlaW4lIGMoIm1PREMuMiIpICB+ICJ5ZUdGUC1tT0RDIiwKICAgICAgZGVncm9uICVpbiUgYygic3RhYmxlLjIiLCAic3RhYmxlLjMiKSB+ICJ5ZUdGUCIKICAgICksCiAgICBkZWdyb24gPSBmYWN0b3IoZGVncm9uICwgbGV2ZWxzID0gYygieWVHRlAtbU9EQyIsICJ5ZUdGUC1DTE4yIiwgInllR0ZQIikpCiAgKSAKYGBgCgpgYGB7cn0KCmFyZWEucHVwMSA8LSBkZl9jb3JTdXBfZmlnICU+JSAKICBmaWx0ZXIoZGVncm9uID09ICJ5ZUdGUC1tT0RDIikgJT4lIAogIGdncGxvdCguLGFlcyh4ID0gQXJlYSwgeSA9IGBQdXAxLXREaW1lcmApKSsKICBnZ3BvaW50ZGVuc2l0eTo6Z2VvbV9wb2ludGRlbnNpdHkoc2l6ZSA9IDAuMiwgZ3VpZGVzID0gRikgKwogICAgICBzdGF0X2NvcihzaXplID0gMykgKwogICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQ0Iiwgc2l6ZSA9IDAuNSkrCiAgICAgIHRoZW1lX2J3KCkgKwogICAgICBsYWJzKHggPSBOVUxMKSArCiAgICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwKSwKICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgyLCJtbSIpLCAKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgICAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjEpKSsKICB5bGFiKCJQdXAxLXREaW1lciBbQS5VXSIpKwogIHhsYWIoIkFyZWEgW0EuVV0iKQoKZG5hLnB1cDEgPC0gZGZfY29yU3VwX2ZpZyAlPiUgCiAgZmlsdGVyKGRlZ3JvbiA9PSAieWVHRlAtbU9EQyIpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IEROQSwgeSA9IGBQdXAxLXREaW1lcmApKSsKICBnZ3BvaW50ZGVuc2l0eTo6Z2VvbV9wb2ludGRlbnNpdHkoc2l6ZSA9IDAuMiwgZ3VpZGVzID0gRikgKwogICAgICBzdGF0X2NvcihzaXplID0gMykgKwogICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQ0Iiwgc2l6ZSA9IDAuNSkrCiAgICAgIHRoZW1lX2J3KCkgKwogICAgICBsYWJzKHggPSBOVUxMKSArCiAgICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwKSwKICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgyLCJtbSIpLCAKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgICAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjEpKSsKICB5bGFiKCJQdXAxLXREaW1lciBbQS5VXSIpKwogIHhsYWIoIkROQSBbQS5VXSIpCgpkbmEuYXJlYSA8LSBkZl9jb3JTdXBfZmlnICU+JQogIGZpbHRlcihkZWdyb24gPT0gInllR0ZQLW1PREMiKSAlPiUgCiAgZ2dwbG90KC4sYWVzKHggPSBETkEsIHkgPSBBcmVhKSkrCiAgZ2dwb2ludGRlbnNpdHk6Omdlb21fcG9pbnRkZW5zaXR5KHNpemUgPSAwLjIsIGd1aWRlcyA9IEYpICsKICAgICAgc3RhdF9jb3Ioc2l6ZSA9IDMpICsKICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkNCIsIHNpemUgPSAwLjUpKwogICAgICB0aGVtZV9idygpICsKICAgICAgbGFicyh4ID0gTlVMTCkgKwogICAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCksCiAgICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMiwibW0iKSwgCiAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgCiAgICAgICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShzaXplID0gMC4xKSkrCiAgeWxhYigiQXJlYSBbQS5VXSIpKwogIHhsYWIoIkROQSBbQS5VXSIpCmBgYAoKYGBge3J9CmdmcEludC5jb3IucGx0IDwtIGRmX2NvclN1cF9maWcgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gMTozKSAlPiUgCiAgIyBmaWx0ZXIoZGVncm9uID09ICJ5ZUdGUC1tT0RDIikgJT4lIAogIGdncGxvdCguLGFlcyh4ID0gdmFsdWUsIHkgPSBHRlApKSsKICBnZ3BvaW50ZGVuc2l0eTo6Z2VvbV9wb2ludGRlbnNpdHkoc2l6ZSA9IDAuMiwgZ3VpZGVzID0gRikgKwogICAgICBzdGF0X2NvcihzaXplID0gMykgKwogICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQ0Iiwgc2l6ZSA9IDAuNSkrCiAgZmFjZXRfd3JhcChkZWdyb25+bmFtZSwgc2NhbGVzID0gImZyZWUiKSsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIGxhYnMoeCA9IE5VTEwpICsKICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzApLAogICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDIsIm1tIiksIAogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDAuMSkpKwogIHhsYWIoIkEuVSIpCmBgYAoKYGBge3J9CnRlc3RfY29yIDwtICgoYXJlYS5wdXAxfGRuYS5wdXAxfGRuYS5hcmVhKS9nZnBJbnQuY29yLnBsdCkrCiAgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoMC4yLCAwLjgpKSsKICBwbG90X2Fubm90YXRpb24odGFnX2xldmVscyA9ICJBIikKCmdnc2F2ZShwbG90ID0gdGVzdF9jb3IsIGZpbGVuYW1lID0gImFyZWEucHVwMS5kbmEuZ2ZwX2Nvci5wZGYiLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA2LjUsIGhlaWdodCA9IDcpCmBgYAoKCiNQYXJ0aWFsIGNvcnJlbGF0aW9ucwpwcGNvcgpgYGB7cn0KI3BhcnRpYWwgY29ycmVsYXRpb25zCnBwQ29yLmxpc3QgPC0gbWxyLmRmMiAlPiUgCiAgZmlsdGVyKHRyZWF0bWVudCA9PSAibm9uZSIpICU+JSBzcGxpdCguJGRlZ3JvbikgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYSA8LSBhICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIGFyZWEsICBkYXBpLnN1bS5iZy5zdWIucHVuY3RhLCByZnAubWVhbi5iZy5zdWIucHVuY3RhLCBnZnAubWVhbi5iZy5hZi5zdWIubmV3KSAlPiUgCiAgICAgIG5hLm9taXQoKQogICAgcHBjb3I6OnBjb3IoYSkKICB9KQoKI2NvcnJlbGF0aW9ucwpjb3IuYWxsIDwtIG1sci5kZjIgJT4lIAogIGZpbHRlcih0cmVhdG1lbnQgPT0gIm5vbmUiKSAlPiUgIAogIHNwbGl0KC4kZGVncm9uKSAlPiUgCiAgbWFwKC4sZnVuY3Rpb24oYSl7CiAgICAgYSA8LSBhICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIGFyZWEsIGRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEscmZwLm1lYW4uYmcuc3ViLnB1bmN0YSwgZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldykgJT4lIAogICAgICBuYS5vbWl0KCkKICAgICBjb3IoYSkKICB9KQoKYGBgCgpgYGB7cn0KcHBDb3IuZGYgPC0gcHBDb3IubGlzdCAlPiUgCiAgbWFwKC4sZnVuY3Rpb24oYSl7CiAgICBhJGVzdGltYXRlICU+JSAKICAgICAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICAgICAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJyZWdyZXNzb3IiKSAlPiUgCiAgICAgIGRwbHlyOjpzZWxlY3QodC5oYWxmLCByZWdyZXNzb3IpICU+JSAKICAgICAgbGVmdF9qb2luKC4sYSRwLnZhbHVlJT4lIAogICAgICAgICAgICAgICAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgICAgICAgICAgICAgICByb3duYW1lc190b19jb2x1bW4odmFyID0gInJlZ3Jlc3NvciIpICU+JSAKICAgICAgICAgICAgICAgICAgcmVuYW1lKCJwLnZhbHVlIiA9ICJ0LmhhbGYiKSAlPiUgCiAgICAgIGRwbHlyOjpzZWxlY3QocC52YWx1ZSwgcmVncmVzc29yKSwgYnkgPSAicmVncmVzc29yIikKICB9KSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJkZWdyb24iKQoKc2luZ2xlLmNvcmUuZGYgPC0gY29yLmFsbCAlPiUgCiAgbWFwKC4sZnVuY3Rpb24oYSl7CiAgICBhJT4lIAogICAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgICByb3duYW1lc190b19jb2x1bW4odmFyID0gInJlZ3Jlc3NvciIpICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIHJlZ3Jlc3NvcikKICB9KSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJkZWdyb24iKSAlPiUgCiAgcmVuYW1lKCJzaW5nbGUuY29yZSI9InQuaGFsZiIpCgpgYGAKCgoKYGBge3J9CnBwQ29vci5maWcgPC0gcHBDb3IuZGYgJT4lIAogIGxlZnRfam9pbiguLHNpbmdsZS5jb3JlLmRmLCBieSA9IGMoImRlZ3JvbiIsInJlZ3Jlc3NvciIpKSAlPiUgCiAgcmVuYW1lKCJQYXJ0aWFsLVBhcml3aXNlIj0idC5oYWxmIiwKICAgICAgICAgIlN0YW5kYXJkLVBhcml3aXNlIiA9ICJzaW5nbGUuY29yZSIpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIlBhcnRpYWwtUGFyaXdpc2UiLCJTdGFuZGFyZC1QYXJpd2lzZSIpKSAlPiUgCiAgIG11dGF0ZShyZWdyZXNzb3IgPSBjYXNlX3doZW4ocmVncmVzc29yID09ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiB+ICJHRlAiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ3Jlc3NvciA9PSAiYXJlYSIgfiAiQXJlYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdyZXNzb3IgPT0gInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiIH4gIlB1cDEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVncmVzc29yID09ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiB+ICJETkEiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ3Jlc3NvciA9PSAidC5oYWxmIiB+ICJoYWxmLWxpZmUiKSwgCiAgICAgICAgICBkZWdyb24gPSBmYWN0b3IoZGVncm9uLCBsZXZlbHMgPSBjKCJ5ZUdGUC1tT0RDIiwieWVHRlAtQ0xOMiIsInllR0ZQIikpLCAKICAgICAgICAgIG5hbWUgPSBmYWN0b3IobmFtZSAsIGxldmVscyA9IGMoIlN0YW5kYXJkLVBhcml3aXNlIiwgIlBhcnRpYWwtUGFyaXdpc2UiKSksIAogICAgICAgICAgc2lnID0gc3RhcnMucHZhbChwLnZhbHVlKSwgCiAgICAgICAgICBzaWcgPSBpZmVsc2Uoc2lnID09ICIgIiwgIk5TIiwgc2lnKSkgJT4lIAogICMgZmlsdGVyKHAudmFsdWUgPCAwLjA1KSAlPiUgCiAgZmlsdGVyKHJlZ3Jlc3NvciAhPSAiaGFsZi1saWZlIikgJT4lIAogIGdncGxvdCguLGFlcyh4ID0gcmVncmVzc29yICwgeSA9IHZhbHVlLCBmaWxsID0gbmFtZSkpKwogIGdlb21fY29sKHdpZHRoID0gMC41LCBwb3NpdGlvbiA9ICJkb2RnZSIpKwogIGZhY2V0X3dyYXAofmRlZ3JvbikrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgc2l6ZSA9IDAuMSkrCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtMC41LDAuNSwgYnkgPSAwLjEpKSsKICB0aGVtZV9wdWJyKCkrCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoNCwibW0iKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjEpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImxpZ2h0c3RlZWxibHVlNCIgLCIgc3RlZWxibHVlNCIpLCBuYW1lID0gTlVMTCkrCiAgeWxhYigiQ29ycmVsYXRpb24gd2l0aCBIYWxmLWxpZmUgIikrCiAgeGxhYigiQ2VsbHVsYXIgZmVhdHVyZXMiKSsKICBsYWJzKHRpdGxlID0gIkMiKQoKcHBDb29yLmZpZwpgYGAKI3BhdGNod29yayBmb3IgNCBjZWxsdWxhciBmZWF0dXJlcyAoYXJlYSwgZ2ZwLCBkYXBpLCBwdXAxKSBhbmQgdC1oYWxmIAoKYGBge3IgZmlnLndpZHRoPSA1LCBmaWcuaGVpZ2h0PSA2fQpnZnAuNGNvci5oZi5wcENvci5wbHQgPC0gKGdmcC42LmNvci5wbHQvdmFyLmV4cC5wbHQvcHBDb29yLmZpZykrCiAgcGxvdF9sYXlvdXQoIGhlaWdodHMgPSBjKDAuNiwwLjIsIDAuMikpCiAgIyBwbG90X2Fubm90YXRpb24odGFnX2xldmVscyA9ICJBIikKCmdmcC40Y29yLmhmLnBwQ29yLnBsdApgYGAKCmBgYHtyfQpnZ3NhdmUocGxvdCA9IGdmcC40Y29yLmhmLnBwQ29yLnBsdCwgZmlsZW5hbWUgPSAiZ2ZwXzRjb3JfaGFsZkxpZmVfcHBjb3IucG5nIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNywgaGVpZ2h0ID0gOSkKCmdnc2F2ZShwbG90ID0gZ2ZwLjRjb3IuaGYucHBDb3IucGx0LCBmaWxlbmFtZSA9ICJnZnBfNGNvcl9oYWxmTGlmZV9wcGNvci5wZGYiLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA3LCBoZWlnaHQgPSA5KQpgYGAKCiN3aXRoIHByb3RlaW4gaW5oaWJpb24KYGBge3J9CnBwQ29yLlBydEluLmxpc3QgPC0gbWxyLmRmICU+JSAKICAgIGZpbHRlcih0cmVhdG1lbnQgIT0gIm5vbmUiKSAlPiUgIAogIGZpbHRlcihpZmVsc2UodHJlYXRtZW50ID09ICI1dU0iLCB0LmhhbGYgPCAxMzguNjI5NCwgdC5oYWxmID09IHQuaGFsZikpICU+JSAKICBzcGxpdCguJHRyZWF0bWVudCkgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYSA8LSBhICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIGFyZWEsIGRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEsIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEsIGdmcC5tZWFuLmJnLmFmLnN1Yi5uZXcpICU+JQogICAgICBuYS5vbWl0KCkKICAgIHBwY29yOjpwY29yKGEpCiAgfSkKCmNvci5QcnRJbi5hbGwgPC0gbWxyLmRmICU+JSAKICAgIGZpbHRlcih0cmVhdG1lbnQgIT0gIm5vbmUiKSAlPiUgIAogIGZpbHRlcihpZmVsc2UodHJlYXRtZW50ID09ICI1dU0iLCB0LmhhbGYgPCAxMzguNjI5NCwgdC5oYWxmID09IHQuaGFsZikpICU+JSAKICBzcGxpdCguJHRyZWF0bWVudCkgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYSA8LSBhICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIGFyZWEsIGRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEsIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEsIGdmcC5tZWFuLmJnLmFmLnN1Yi5uZXcpICU+JSAKICAgICAgbmEub21pdCgpCiAgICBjb3IoYSkKICB9KQoKYGBgCgpgYGB7cn0KcHBDb3IuUHJ0SW4uZGYgPC0gcHBDb3IuUHJ0SW4ubGlzdCAlPiUgCiAgbWFwKC4sZnVuY3Rpb24oYSl7CiAgICBhJGVzdGltYXRlICU+JSAKICAgICAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICAgICAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJyZWdyZXNzb3IiKSAlPiUgCiAgICAgIGRwbHlyOjpzZWxlY3QodC5oYWxmLCByZWdyZXNzb3IpICU+JSAKICAgICAgbGVmdF9qb2luKC4sYSRwLnZhbHVlJT4lIAogICAgICAgICAgICAgICAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgICAgICAgICAgICAgICByb3duYW1lc190b19jb2x1bW4odmFyID0gInJlZ3Jlc3NvciIpICU+JSAKICAgICAgICAgICAgICAgICAgcmVuYW1lKCJwLnZhbHVlIiA9ICJ0LmhhbGYiKSAlPiUgCiAgICAgIGRwbHlyOjpzZWxlY3QocC52YWx1ZSwgcmVncmVzc29yKSwgYnkgPSAicmVncmVzc29yIikKICB9KSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJ0cmVhdG1lbnQiKQoKc2luZ2xlLmNvcmUuUHJ0bi5kZiA8LSBjb3IuUHJ0SW4uYWxsICU+JSAKICBtYXAoLixmdW5jdGlvbihhKXsKICAgIGElPiUgCiAgICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgICAgIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAicmVncmVzc29yIikgJT4lIAogICAgICBkcGx5cjo6c2VsZWN0KHQuaGFsZiwgcmVncmVzc29yKQogIH0pICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gInRyZWF0bWVudCIpICU+JSAKICByZW5hbWUoInNpbmdsZS5jb3JlIj0idC5oYWxmIikKYGBgCgpjb3JyZWxhdGlvbiBvZiBwdXAxIHdpdGggbU9EQyB3aXRoIHRyZWF0ZWQgd2l0aCBwcm90ZWFzb21lIGluaGliaXRvcnMKYGBge3J9CnBwY29yLmZpZy5kZiA8LSBwcENvci5QcnRJbi5kZiAlPiUgCiAgbGVmdF9qb2luKC4sc2luZ2xlLmNvcmUuUHJ0bi5kZiwgYnkgPSBjKCJ0cmVhdG1lbnQiLCJyZWdyZXNzb3IiKSkgJT4lIAogIGZpbHRlcighKHRyZWF0bWVudCAlaW4lIGMoImRtc28xIiwiNTB1TSIpKSkgJT4lIAogIHJlbmFtZSgiUGFydGlhbC1QYXJpd2lzZSI9InQuaGFsZiIsCiAgICAgICAgICJTdGFuZGFyZC1QYXJpd2lzZSIgPSAic2luZ2xlLmNvcmUiKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKCJQYXJ0aWFsLVBhcml3aXNlIiwiU3RhbmRhcmQtUGFyaXdpc2UiKSkgJT4lIAogICBtdXRhdGUocmVncmVzc29yID0gY2FzZV93aGVuKHJlZ3Jlc3NvciA9PSAiZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldyIgfiAiR0ZQIiAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdyZXNzb3IgPT0gImFyZWEiIH4gIkFyZWEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVncmVzc29yID09ICJyZnAubWVhbi5iZy5zdWIucHVuY3RhIiB+ICJQdXAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ3Jlc3NvciA9PSAiZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSIgfiAiRE5BIiAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdyZXNzb3IgPT0gInQuaGFsZiIgfiAiaGFsZi1saWZlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gcmVncmVzc29yKSwgCiAgICAgICAgICB0cmVhdG1lbnQgPSBmYWN0b3IodHJlYXRtZW50LCBsZXZlbHMgPSBjKCJkbXNvMSIsIjUwdU0iLCJkbXNvMiIsIjF1TSIsIjIuNXVNIiwiNXVNIikpLCAKICAgICAgICAgIG5hbWUgPSBmYWN0b3IobmFtZSAsIGxldmVscyA9IGMoIlN0YW5kYXJkLVBhcml3aXNlIiwgIlBhcnRpYWwtUGFyaXdpc2UiKSksIAogICAgICAgICAgc2lnID0gc3RhcnMucHZhbChwLnZhbHVlKSwgCiAgICAgICAgICBzaWcgPSBpZmVsc2Uoc2lnID09ICJcICIsICJOLlMiLCBzaWcpKQogICAgICAgICAgIyBuZXcudmFsdWUgPSBpZmVsc2UoKG5hbWUgPT0gIlBhcnRpYWwtUGFyaXdpc2UiICYgcC52YWx1ZSA+IDAuMDUpLCAwLCB2YWx1ZSkpICU+JSAKICAjIGZpbHRlcihwLnZhbHVlIDwgMC4wNSkgJT4lIApwcGNvci5maWcuZGYgJT4lIAogIGZpbHRlcighKHJlZ3Jlc3NvciAlaW4lIGMoImhhbGYtbGlmZSIsICJzaGFwZSIpKSwgCiAgICAgICAgIHJlZ3Jlc3NvciA9PSAiUHVwMSIsIAogICAgICAgICB0cmVhdG1lbnQgJWluJSBjKCJkbXNvMiIsIjF1TSIsIjIuNXVNIiwiNXVNIikpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IHRyZWF0bWVudCAsIHkgPXZhbHVlLCBmaWxsID0gbmFtZSkpKwogIGdlb21fY29sKHdpZHRoID0gMC41LCBwb3NpdGlvbiA9ICJkb2RnZSIpKwogIGdlb21fdGV4dChkYXRhID0gcHBjb3IuZmlnLmRmICU+JSAKICAgICAgICAgICAgICBmaWx0ZXIoIShyZWdyZXNzb3IgJWluJSBjKCJoYWxmLWxpZmUiLCAic2hhcGUiKSksIAogICAgICAgICByZWdyZXNzb3IgPT0gIlB1cDEiLCAKICAgICAgICAgdHJlYXRtZW50ICVpbiUgYygiZG1zbzIiLCIxdU0iLCIyLjV1TSIsIjV1TSIpKSAsIAogICAgICAgICBhZXMobGFiZWwgPSBzaWcpLCBudWRnZV94ID0gLTAuMSkrCiAgIyBmYWNldF93cmFwKH50cmVhdG1lbnQsIG5yb3cgPSAxKSsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKC0wLjUsMC41LCBieSA9IDAuMSkpKwogIHRoZW1lX3B1YnIoKSsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCg0LCJtbSIpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJsaWdodHN0ZWVsYmx1ZTQiICwiIHN0ZWVsYmx1ZTQiKSwgbmFtZSA9IE5VTEwpKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApKwogIHlsYWIoIkNvcnJlbGF0aW9uIG9mIFB1cDEgd2l0aCBIYWxmLWxpZmUgIikrCiAgeGxhYigiUHJvdGVpbiBpbmhpYml0b3IgdHJlYXRtZW50IChNRzEzMikiKQpgYGAKCiN3aGVuIHlvdSBub3JtYWxpemUgcHVwMSB3aXRoIHRoZSBhcmVhCmBgYHtyfQptbHIuZGYgJT4lCiAgbXV0YXRlKGRtID0gbG9nMTAoZG0pKSAlPiUgCiAgZmlsdGVyKGRlZ3JvbiAlaW4lIGMoIm1PREMuMiIsICJjbG4yLjMiLCAiY2xuMi40IiwgInN0YWJsZS4yIiwgInN0YWJsZS4zIikpICU+JQogIGRwbHlyOjpzZWxlY3QodC5oYWxmLAogICAgICAgICByZWdyZXNzb3JzLAogICAgICAgICBkZWdyb24pICU+JQogIHJlbmFtZSgKICAgICJHRlAiID0gImdmcC5tZWFuLmJnLmFmLnN1Yi5uZXciLAogICAgIlB1cDEtdERpbWVyIiA9ICJyZnAubWVhbi5iZy5zdWIucHVuY3RhIiwKICAgICJETkEiID0gImRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEiLAogICAgIkFyZWEiID0gImFyZWEiCiAgKSAlPiUKICBtdXRhdGUobm9ybS5wdXAxID0gYFB1cDEtdERpbWVyYC9BcmVhKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDI6Nyw5KSkgJT4lCiAgbXV0YXRlKGRlZ3JvbiA9IGNhc2Vfd2hlbigKICAgICAgZGVncm9uICVpbiUgYygiY2xuMi4zIiwgImNsbjIuMiIsICJjbG4yIiwgImNsbjIuNCIpIH4gInllR0ZQLUNMTjIiLAogICAgICBkZWdyb24gJWluJSBjKCJtT0RDLjIiLCAibU9EQyIpICB+ICJ5ZUdGUC1tT0RDIiwKICAgICAgZGVncm9uICVpbiUgYygic3RhYmxlIiwgInN0YWJsZS4yIiwgInN0YWJsZS4zIikgfiAieWVHRlAiCiAgICApLAogICAgZGVncm9uID0gZmFjdG9yKGRlZ3JvbiAsIGxldmVscyA9IGMoInllR0ZQLW1PREMiLCAieWVHRlAtQ0xOMiIsICJ5ZUdGUCIpKQogICkgJT4lCiAgZmlsdGVyKCEobmFtZSAlaW4lIGMoInNoYXBlIiwiZG0iKSkpICU+JSAKICBnZ3Bsb3QoLiwgYWVzKHggPSB2YWx1ZSwgeSA9IHQuaGFsZikpICsKICAgICAgZ2dwb2ludGRlbnNpdHk6Omdlb21fcG9pbnRkZW5zaXR5KHNpemUgPSAwLjIsIGd1aWRlcyA9IEYpICsKICAgICAgc3RhdF9jb3Ioc2l6ZSA9IDIpICsKICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkNCIsIHNpemUgPSAwLjUpKwogICAgICBmYWNldF93cmFwKGRlZ3JvbiB+IG5hbWUsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDQpICsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIGxhYnMoeCA9IE5VTEwpICsKICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzApLAogICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDIsIm1tIiksIAogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKwogIHlsYWIoIkhhbGYtTGlmZSBbbWluLl0iKSsKICB4bGFiKCJBLlUiKQpgYGAKCg==